package cn.com.cifi.mars.service.impl;

import static org.hamcrest.CoreMatchers.nullValue;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Month;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;

import cn.com.cifi.mars.bean.bo.DictionaryCodeBO;
import cn.com.cifi.mars.bean.bo.MdmBuildAreaBO;
import cn.com.cifi.mars.bean.bo.MdmBuildAreaDetailBO;
import cn.com.cifi.mars.bean.bo.MyRoomBO;
import cn.com.cifi.mars.bean.bo.PanoPlanCastDecisionBO;
import cn.com.cifi.mars.bean.bo.PortalTodoBo;
import cn.com.cifi.mars.bean.bo.PriceValueCastDecisionAllOrgEXTBO;
import cn.com.cifi.mars.bean.bo.PriceValueCastDecisionEXTBO;
import cn.com.cifi.mars.bean.dto.MymContractDto;
import cn.com.cifi.mars.bean.dto.NOSRoomCompensationDto;
import cn.com.cifi.mars.bean.dto.NosTradedataDto;
import cn.com.cifi.mars.bean.vo.price.NoticePriceCompareVo;
import cn.com.cifi.mars.bean.vo.price.PriceValueCompareVO;
import cn.com.cifi.mars.bean.vo.sys.rsp.GroupUserVo;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.constant.CodeEnum;
import cn.com.cifi.mars.constant.Constants;
import cn.com.cifi.mars.constant.FetchNnumberEnum;
import cn.com.cifi.mars.constant.HrOrgTypeEunm;
import cn.com.cifi.mars.constant.IsDeleteEnum;
import cn.com.cifi.mars.constant.IsSplitEnum;
import cn.com.cifi.mars.constant.MarketingEunm;
import cn.com.cifi.mars.constant.ModuleTypeEunm;
import cn.com.cifi.mars.constant.NodeEnum;
import cn.com.cifi.mars.constant.NoticeAffectedEnum;
import cn.com.cifi.mars.constant.NumberEnum;
import cn.com.cifi.mars.constant.OperatorTypeEnum;
import cn.com.cifi.mars.constant.OrgTypeEunm;
import cn.com.cifi.mars.constant.ProcessingModeEnum;
import cn.com.cifi.mars.constant.ProcessingStateEnum;
import cn.com.cifi.mars.constant.SalyTypeEnum;
import cn.com.cifi.mars.constant.StageStatusEnum;
import cn.com.cifi.mars.constant.SupplyEnum;
import cn.com.cifi.mars.constant.TodoOrgTypeEnum;
import cn.com.cifi.mars.constant.TodoTypeCodeEnum;
import cn.com.cifi.mars.constant.VersionCreateEnum;
import cn.com.cifi.mars.constant.VersionEventEnum;
import cn.com.cifi.mars.constant.VersionIdTypeEnum;
import cn.com.cifi.mars.constant.VersionStatusEnum;
import cn.com.cifi.mars.constant.VersionTypeEunm;
import cn.com.cifi.mars.constant.WhetherEnum;
import cn.com.cifi.mars.entity.ApprovalBill;
import cn.com.cifi.mars.entity.MdmProject;
import cn.com.cifi.mars.entity.MdmStage;
import cn.com.cifi.mars.entity.MymRooms;
import cn.com.cifi.mars.entity.PanoplanBuildPlanItem;
import cn.com.cifi.mars.entity.PanoplanBuildPlanItemDetail;
import cn.com.cifi.mars.entity.PriceValueOrg;
import cn.com.cifi.mars.entity.PriceValueOrgBackups;
import cn.com.cifi.mars.entity.PriceVersion;
import cn.com.cifi.mars.entity.PriceVersionBackups;
import cn.com.cifi.mars.entity.StagePartNers;
import cn.com.cifi.mars.entity.SysNotice;
import cn.com.cifi.mars.entity.common.IdmUser;
import cn.com.cifi.mars.entity.common.ProjectByStages;
import cn.com.cifi.mars.entity.common.SysDictionary;
import cn.com.cifi.mars.entity.common.SysProjectFetchNumber;
import cn.com.cifi.mars.mapper.mars.ApprovalBillMapper;
import cn.com.cifi.mars.mapper.mars.PriceValueOrgMapper;
import cn.com.cifi.mars.mapper.mars.PriceVersionMapper;
import cn.com.cifi.mars.mapper.mars.ProjectMapper;
import cn.com.cifi.mars.mapper.mars.SysNoticeMapper;
import cn.com.cifi.mars.service.BuildAreaService;
import cn.com.cifi.mars.service.CommonService;
import cn.com.cifi.mars.service.DmOdsMyVsMarsSContractService;
import cn.com.cifi.mars.service.DmOdsNosTradedataviewformarsService;
import cn.com.cifi.mars.service.IdmUserService;
import cn.com.cifi.mars.service.MymRoomsService;
import cn.com.cifi.mars.service.PanoplanBuildPlanService;
import cn.com.cifi.mars.service.PriceValueOrgBackupsService;
import cn.com.cifi.mars.service.PriceValueOrgService;
import cn.com.cifi.mars.service.PriceVersionBackupsService;
import cn.com.cifi.mars.service.PriceVersionService;
import cn.com.cifi.mars.service.PriceVersionValueOrgService;
import cn.com.cifi.mars.service.ProjectLockRecordService;
import cn.com.cifi.mars.service.ProjectService;
import cn.com.cifi.mars.service.SignPlanVersionService;
import cn.com.cifi.mars.service.StagePartNersService;
import cn.com.cifi.mars.service.StageService;
import cn.com.cifi.mars.service.SupplyPlanVersionService;
import cn.com.cifi.mars.service.SysDictionaryService;
import cn.com.cifi.mars.service.SysNoticeService;
import cn.com.cifi.mars.service.SysProjectFetchNumberService;
import cn.com.cifi.mars.service.VersionLogService;
import cn.com.cifi.mars.util.DateUtils;
import cn.com.cifi.mars.util.LocalDateTimeUtils;
import cn.com.cifi.mars.util.StrUtils;
import cn.com.cifi.mars.util.SynchrolockUtil;
import cn.com.cifi.mars.util.UUIDUtils;
import cn.com.cifi.mars.util.VersionNameUtils;
import cn.com.cifi.mars.util.VersionUtils;

@Service
public class PriceVersionValueOrgServiceImpl implements PriceVersionValueOrgService {

    @Autowired
    private PriceVersionMapper priceVersionMapper;

    @Autowired
    private PanoplanBuildPlanService panoplanBuildPlanService;

    @Autowired
    private ProjectService projectService;

    @Autowired
    private StageService stageService;

    @Autowired
    private PriceValueOrgMapper priceValueOrgMapper;

    @Autowired
    private SysDictionaryService sysDictionaryService;

    @Autowired
    private PriceVersionService priceVersionService;

    @Autowired
    private BuildAreaService buildAreaService;

    @Autowired
    private SysProjectFetchNumberService sysProjectFetchNumberService;

    @Autowired
    private PriceValueOrgService priceValueOrgService;

    @Autowired
    private MymRoomsService mymRoomsService;

    @Autowired
    private SysNoticeService sysNoticeService;

    @Autowired
    private SupplyPlanVersionService supplyPlanVersionService;

    @Autowired
    private PriceVersionServiceImpl priceVersionServiceImpl;

    @Autowired
    private ApprovalBillMapper approvalBillMapper;

    @Autowired
    private SysNoticeMapper sysNoticeMapper;

    @Autowired
    private MymRoomInfoServiceImpl mymRoomInfoServiceImpl;

    @Autowired
    private SignPlanVersionService signPlanVersionService;

    @Autowired
    private DmOdsMyVsMarsSContractService dmOdsMyVsMarsSContractService;

    @Autowired
    private DmOdsNosTradedataviewformarsService dmOdsNosTradedataviewformarsService;

    @Autowired
    private StagePartNersService stagePartNersService;

    @Autowired
    private VersionLogService versionLogService;

    @Autowired
    private CommonService commonService;

    @Autowired
    private ProjectMapper projectMapper;

    @Autowired
    private IdmUserService idmUserService;

    @Autowired
    private ProjectLockRecordService projectLockRecordService;

    @Autowired
    private PriceVersionBackupsService priceVersionBackupsService;

    @Autowired
    private PriceValueOrgBackupsService priceValueOrgBackupsService;

    @Autowired
    private SynchrolockUtil synchrolockUtil;

    static List<String> isParkList = Arrays.asList("139","140","141","142","154");

    @Value("${price_notice_pc_url}")
    private String priceNoticePcUrl;

    @Value("${mobile_task_url}")
    private String priceNoticeAppUrl;

    private static final Logger logger = LoggerFactory.getLogger(PriceVersionValueOrgServiceImpl.class);

    
    /**
     *  投资版货值自动生成
     * @param projectFid 分期id
     * @param createType 创建类型
     * @param createUser 创建人
     * @return 版本id
     */
    @Override
    public String createSysCastDecisionVersion(String projectFid, String createType, IdmUser createUser, Integer lable, String instId) {
        LocalDateTime now = LocalDateTime.now();

        //查询指定分期信息
        MdmStage mdmStage = getMdmStageByStageId(projectFid);

        //根据分期查询项目下所有分期
        List<String> stageIds = getStagesByStageId(projectFid);

        //投资版创建校验
        investmentCreateVersionVerification(projectFid, createType, mdmStage, stageIds);

        //获取最新的投资版楼栋计划
        PanoPlanCastDecisionBO panoPlanCastDecisionBO = panoplanBuildPlanService.selectNewestByFid(projectFid, Arrays.asList(VersionTypeEunm.INVESTMENT.getValue()), IsDeleteEnum.NO.getKey());

        //将节点为取预售证时间的存储在指定Map中
        Map<String, LocalDateTime> openTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeVirtualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        List<PanoplanBuildPlanItemDetail> details = panoPlanCastDecisionBO.getDetails();
        if(CollectionUtils.isNotEmpty(details)){
            for (int i = 0;i < details.size(); i++) {
                castDecisionTimeItemMapInfo(openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, details, i);
            }
        }

        //分期有可售或阶段性自持产品构成校验
        investmentStageSelfVerification(panoPlanCastDecisionBO, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap);

        //查询最新审批通过的价格管理投资版
        String oldVersionId = "";
        String oldVersionNum = "";
        Map<String, PriceValueCastDecisionAllOrgEXTBO> preProductMap = new HashMap<String, PriceValueCastDecisionAllOrgEXTBO>();
        Map<String, PriceValueCastDecisionAllOrgEXTBO> preParkingMap = new HashMap<String, PriceValueCastDecisionAllOrgEXTBO>();
        Map<String, PriceValueCastDecisionAllOrgEXTBO> preNotSaleParkingMap = new HashMap<String, PriceValueCastDecisionAllOrgEXTBO>();
        PriceVersion oldPriceVersion = priceVersionMapper.selectNewestVersionByFid(projectFid, VersionTypeEunm.INVESTMENT.getKey(), Arrays.asList(VersionStatusEnum.SYSGENERATION.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey()), IsDeleteEnum.NO.getKey());
        if (oldPriceVersion != null){
        	if(!(createType.equals(VersionCreateEnum.EXCEPTIONCREATE.getKey()) || createType.equals(VersionCreateEnum.AUTOMATICCREATE.getKey())) ) {
        		throw new MsgException(CodeEnum.EXIST_INVESTMENT_VERSIONS);
        	}
            oldVersionId = oldPriceVersion.getId();
            oldVersionNum = oldPriceVersion.getVersionNum();
            //获取上版本产品构成以及可售车位和待售车位数据
            List<PriceValueCastDecisionAllOrgEXTBO> prePriceValueOrgList = priceValueOrgMapper.selectCastDecisionAllOrg(oldVersionId, IsDeleteEnum.NO.getKey());
            for (PriceValueCastDecisionAllOrgEXTBO preOrg : prePriceValueOrgList){
                castDecisionPreOrgInfo(preProductMap, preParkingMap, preNotSaleParkingMap, preOrg);
            }
        }

        //操盘方式
        String market = getStagePartnerToMarket(mdmStage);

        //创建新版本
        PriceVersion newVersion = createInvestmentVersionInfo(oldPriceVersion, oldVersionId, oldVersionNum, mdmStage
                                            , createType, createUser, lable, panoPlanCastDecisionBO, market, now);

        //创建分期
        PriceValueOrg projectOrg = createStageValueInfo(now, mdmStage, newVersion.getId());

        //创建组团
        Map<String, PriceValueOrg> groupInsertMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> groupMap = new HashMap<String, PriceValueOrg>();
        List<PanoplanBuildPlanItem> groupItems = panoPlanCastDecisionBO.getGroupItems();
        for(PanoplanBuildPlanItem groupItem : groupItems) {
            castDecisionGroupItemInfo(now, projectOrg, groupInsertMap, groupMap, groupItem, newVersion.getId());
        }

        //创建批次
        Map<String, PriceValueOrg> batchInsertMap = new HashMap<String, PriceValueOrg>();
        Map<String, String> batchMap = new HashMap<String, String>();
        List<PanoplanBuildPlanItem> batchItems = panoPlanCastDecisionBO.getBatchItems();
        for(PanoplanBuildPlanItem batchItem : batchItems){
            castDecisionBatchItemInfo(now, newVersion.getId(), groupMap, batchInsertMap, batchMap, batchItem);
        }

        //构建product
        Map<String, PriceValueOrg> productMap = new HashMap<String, PriceValueOrg>();
        List<PanoplanBuildPlanItem> pproductItems = panoPlanCastDecisionBO.getProductItems();

        //找上级分类
        castDecisionProductItemToDic(newVersion, now, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, batchMap, productMap, pproductItems);

        //判断产品构成下经营方式是否全部为不可售，如果是的话则不能创建版本
//        if(notSalyTypeList.size() == productMap.size()){
//            throw new MsgException(CodeEnum.NON_BUILD_SALY_TYPE_ERROR);
//        }

        //从新复制产品构成和车位信息
        List<PriceValueOrg> productList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> parkingList = new ArrayList<PriceValueOrg>();
        for (Map.Entry<String, PriceValueOrg> productmap : productMap.entrySet()) {
            castDecisionProductInsertInfo(newVersion, preProductMap, productList, parkingList, productmap);
        }

        //货值汇总
        List<PriceValueOrg> productInsertList = new ArrayList<PriceValueOrg>();
        for (PriceValueOrg productOrg : productList) {
            castDecisionProductSumInfo(batchInsertMap, productInsertList, productOrg);
        }

        List<PriceValueOrg> batchInsertList = new ArrayList<PriceValueOrg>();
        if (CollectionUtils.isNotEmpty(batchInsertMap)){
            castDecisionBatchSumInfo(groupInsertMap, batchInsertMap, batchInsertList);
        }

        List<PriceValueOrg> groupInsertList = new ArrayList<PriceValueOrg>();
        if (CollectionUtils.isNotEmpty(groupInsertMap)) {
            castDecisionGroupSumInfo(projectOrg, groupInsertMap, groupInsertList);
        }

        List<PriceValueOrg> projectList = Arrays.asList(projectOrg);
        saveInvestmentValueInfo(newVersion, parkingList, productInsertList, batchInsertList, groupInsertList, projectList);

        //货值投资版代办信息
        priceInvestmentNoticeInfo(projectFid, createUser, now, newVersion);

        //版本日志
        priceVersionLogInfo(createType, instId, now, mdmStage, newVersion, newVersion.getCreateBy());

        return newVersion.getId();
    }

    private void castDecisionTimeItemMapInfo(Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, List<PanoplanBuildPlanItemDetail> details, int i) {
        PanoplanBuildPlanItemDetail panoplanBuildPlanItemDetail = details.get(i);
        String nodeCode = panoplanBuildPlanItemDetail.getNodeCode();
        if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00002.getKey())) {
            openTimeMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getPlannedFinishDate());
            openTimeActualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getActualFinishDate());
        } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00001.getKey())) {
            advanceSaleTimeMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getPlannedFinishDate());
            advanceSaleTimeActualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getActualFinishDate());
        } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00002.getKey())) {
            supplyTimeMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getPlannedFinishDate());
            supplyTimeActualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getActualFinishDate());
            supplyTimeVirtualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getVirtualFinishDate());
        } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00003.getKey())) {
            openSaleTimeMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getPlannedFinishDate());
            openSaleTimeActualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getActualFinishDate());
        } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00003.getKey())) {
            cappingTimeMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getPlannedFinishDate());
            cappingTimeActualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getActualFinishDate());
        } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00004.getKey())) {
            completedTimeMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getPlannedFinishDate());
            completedTimeActualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getActualFinishDate());
        } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00006.getKey())) {
            carryOverTimeMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getPlannedFinishDate());
            carryOverTimeActualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getActualFinishDate());
        } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00005.getKey())) {
            actualDeliveryTimeMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getPlannedFinishDate());
            actualDeliveryTimeActualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getActualFinishDate());
        } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.NODE_000.getKey())) {
            contractDeliveryTimeMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getPlannedFinishDate());
            contractDeliveryTimeActualMap.put(panoplanBuildPlanItemDetail.getPkId(), panoplanBuildPlanItemDetail.getActualFinishDate());
        }
    }

    private void castDecisionGroupSumInfo(PriceValueOrg projectOrg, Map<String, PriceValueOrg> groupInsertMap, List<PriceValueOrg> groupInsertList) {
        for (Map.Entry<String, PriceValueOrg> groupOrgMap : groupInsertMap.entrySet()) {
            PriceValueOrg groupOrg = groupOrgMap.getValue();
            valueUpSummary(projectOrg, groupOrg);
            groupInsertList.add(groupOrg);
        }
    }

    private void castDecisionProductSumInfo(Map<String, PriceValueOrg> batchInsertMap, List<PriceValueOrg> productInsertList, PriceValueOrg productOrg) {
        String businessType = productOrg.getBusinessType();
        if (businessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()) || businessType.equals(SalyTypeEnum.RENTED.getKey())) {
            productInsertList.add(productOrg);
            return;
        }
        PriceValueOrg batchOrg = batchInsertMap.get(productOrg.getPid());
        valueUpSummary(batchOrg, productOrg);
        batchInsertMap.put(productOrg.getPid(), batchOrg);
        productInsertList.add(productOrg);
    }

    private void castDecisionProductItemInfo(LocalDateTime now, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, PriceVersion newVersion, Map<String, String> batchMap, Map<String, PriceValueOrg> productMap, Map<String, DictionaryCodeBO> dicMap, List<PriceValueOrg> notSalyTypeList, PanoplanBuildPlanItem productItem) {
        String code = productItem.getBatchId() + "&" + productItem.getBatchNum() + "&" + productItem.getProductTypeNum() + "&" + productItem.getDecorateName() + "&" + productItem.getSaleType() + "&" + productItem.getProType();
        PriceValueOrg priceValueOrg = createInvestmentProductValueInfo(productItem, newVersion, batchMap,
                dicMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap,
                supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap,
                cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap,
                actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, now);
        if (productItem.getSaleNum() != null && (productItem.getSaleNum().equals(SalyTypeEnum.RENTED.getKey()) || productItem.getSaleNum().equals(SalyTypeEnum.NOT_RENTABLE.getKey()))) {
            notSalyTypeList.add(priceValueOrg);
        }
        productMap.put(code, priceValueOrg);
    }

    private void castDecisionGroupItemInfo(LocalDateTime now, PriceValueOrg projectOrg, Map<String, PriceValueOrg> groupInsertMap, Map<String, PriceValueOrg> groupMap, PanoplanBuildPlanItem groupItem, String id) {
        PriceValueOrg priceValueOrg = createInvestmentGroupValueInfo(now, id, projectOrg, groupItem);
        groupInsertMap.put(priceValueOrg.getId(), priceValueOrg);
        groupMap.put(groupItem.getBatchId(), priceValueOrg);
    }

    /**
     *  根据分期id查询项目下所有分期信息
     * @param projectFid 分期id
     * @return
     */
    private List<String> getStagesByStageId(String projectFid) {
        List<MdmStage> stages = stageService.selectStagesByprojectFid(projectFid);
        List<String> stageIds = Optional.of(stages).orElseGet(ArrayList::new)
                .stream().map(MdmStage::getProjectFid)
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(stages)) {
            throw new MsgException(CodeEnum.STAGE_NON_EXISTENT_TO_IDM);
        }
        return stageIds;
    }

    /**
     * 查询项目分期信息
     * @param projectFid 分期id
     * @return
     */
    private MdmStage getMdmStageByStageId(String projectFid) {
        MdmStage mdmStage = stageService.selectById(projectFid);
        if (mdmStage == null) {
            throw new MsgException(CodeEnum.STAGE_NON_EXISTENT);
        } else {
            String status = mdmStage.getStatus();
            if (StringUtils.isNotEmpty(status) && status.equals(StageStatusEnum.INACTIVE.getKey())) {
                throw new MsgException(CodeEnum.CREATE_STAGE_INACTIVE_ERROR);
            }
        }
        return mdmStage;
    }

    /**
     *  投资版计算产品构成下车位信息
     */
    private PriceValueOrg calculationInvestmentProductValueInfo(PriceValueOrg productOrg, String code, Map<String, PriceValueCastDecisionAllOrgEXTBO> preProductMap, String orgCode, Integer productOrgNum, PriceVersion newVersion, List<PriceValueOrg> parkingList) {
        //复制上版本产品构成信息
        Integer preParkingNum = 0;
        BigDecimal preAveragePriceParking = new BigDecimal(0);
        PriceValueCastDecisionAllOrgEXTBO preProductOrg = preProductMap.get(code);
        if (preProductOrg != null){
            String preProductCode = preProductOrg.getProductCode();
            if(isParkList.contains(preProductCode)){
                productOrg.setAveragePriceParking(preProductOrg.getAveragePriceParking());
                productOrg.setNotCommodityValue(BigDecimalMUL(preProductOrg.getAveragePriceParking(), new BigDecimal(productOrgNum)));
                productOrg.setCommodityValue(preProductOrg.getCommodityValue());

                preParkingNum = preProductOrg.getParkingNum()==null?0:preProductOrg.getParkingNum();
                preAveragePriceParking = preProductOrg.getAveragePriceParking()==null?new BigDecimal(0):preProductOrg.getAveragePriceParking();
            }else{
                productOrg.setAveragePriceHouse(preProductOrg.getAveragePriceHouse());
                productOrg.setHouseCommodityValue(BigDecimalMUL(preProductOrg.getAveragePriceHouse(), productOrg.getSaleArea()));
            }
        }

        //赋值上版本可售车位信息和待售车位信息
        if (isParkList.contains(orgCode)){

            //剩余未推售 = 新的主数据⻋位楼栋总⻋位数 - 上⼀版⻋位楼栋总可售⻋位数 - 上⼀版⻋位楼栋已定价⾃持⻋位数；
            Integer buildNum = productOrg.getParkingNum();
            Integer subNum = buildNum - preParkingNum;
            if(subNum < 0) {
            	subNum = 0;
            }
            //新的可售未定价⻋位数 = 新的主数据⻋位楼栋总⻋位数 – 新归集的已售⻋位数 – 新归集的已定价未售⻋位数 - 新归集的已定价⾃持⻋位数 - 剩余未推售；
            // 如果新的可售未定价⻋位数 < 0，新的可售未定价⻋位数=0；
            Integer parkingNum = buildNum - subNum;
            if(parkingNum < 0){
                parkingNum = 0;
            }

            //新的未推售⻋位数 = 新的主数据⻋位楼栋总⻋位数 – 新归集的已售⻋位数 – 新归集的已定价未售⻋位数- 新的可售未定价⻋位数 - 新归集的已定价⾃持⻋位数；
            // 如果新的未推售⻋位数 < 0，新的未推售⻋位数=0；
            Integer forsaleParkingNum = buildNum - parkingNum;
            if(forsaleParkingNum < 0){
                forsaleParkingNum = 0;
            }

            PriceValueOrg parkingOrg = new PriceValueOrg();
            String parkingId = UUIDUtils.create();
            parkingOrg.setId(parkingId);
            parkingOrg.setPid(productOrg.getId());
            parkingOrg.setVersionId(newVersion.getId());
            parkingOrg.setType(OrgTypeEunm.ORG_SALING_PARKING.getKey());
            parkingOrg.setOrgCode(OrgTypeEunm.ORG_SALING_PARKING.getKey());
            parkingOrg.setOrgName(OrgTypeEunm.ORG_SALING_PARKING.getValue());
            parkingOrg.setNum(parkingNum);
            parkingOrg.setParkingNum(parkingNum);
            parkingOrg.setAveragePriceParking(preAveragePriceParking);
            BigDecimal notValue = BigDecimalMUL(preAveragePriceParking, new BigDecimal(parkingNum));
            parkingOrg.setNotCommodityValue(notValue);
            parkingOrg.setIsParking(IsDeleteEnum.YES.getKey());
            parkingOrg.setIsDelete(IsDeleteEnum.NO.getKey());
            parkingOrg.setIsSplit(IsDeleteEnum.NO.getKey());
            parkingOrg.setTotalNum(buildNum);
            parkingList.add(parkingOrg);

            if(forsaleParkingNum > 0){
                PriceValueOrg forSaleParkingOrg = new PriceValueOrg();

                forSaleParkingOrg.setId(UUIDUtils.create());
                forSaleParkingOrg.setPid(productOrg.getId());
                forSaleParkingOrg.setVersionId(newVersion.getId());
                forSaleParkingOrg.setType(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey());
                forSaleParkingOrg.setOrgCode(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey());
                forSaleParkingOrg.setOrgName(OrgTypeEunm.ORG_NOT_SALING_PARKING.getValue());
                forSaleParkingOrg.setNum(forsaleParkingNum);
                forSaleParkingOrg.setForsaleParkingNum(forsaleParkingNum);
                BigDecimal forSaleValuePrice = BigDecimalMUL(preAveragePriceParking, new BigDecimal(forsaleParkingNum));
                forSaleParkingOrg.setCommodityValue(forSaleValuePrice);
                forSaleParkingOrg.setIsParking(IsDeleteEnum.YES.getKey());
                forSaleParkingOrg.setIsDelete(IsDeleteEnum.NO.getKey());
                forSaleParkingOrg.setIsSplit(IsDeleteEnum.NO.getKey());
                forSaleParkingOrg.setTotalNum(buildNum);
                parkingList.add(forSaleParkingOrg);

                productOrg.setForsaleParkingNum(forsaleParkingNum);
                productOrg.setCommodityValue(forSaleValuePrice);
            }

            //重新计算货值信息
            productOrg.setAveragePriceParking(preAveragePriceParking);
            productOrg.setParkingNum(parkingNum);
            productOrg.setNotCommodityValue(notValue);
        }

        return  productOrg;
    }

    /**
     *  创建投资版产品构成
     */
    private PriceValueOrg createInvestmentProductValueInfo(PanoplanBuildPlanItem productItem, PriceVersion newVersion, Map<String, String> batchMap,
                                                           Map<String, DictionaryCodeBO> dicMap, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap,
                                                           Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap,
                                                           Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap,
                                                           Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap,
                                                           Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap,
                                                           Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap,
                                                           Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, LocalDateTime now) {

        PriceValueOrg priceValueOrg = new PriceValueOrg();

        //赋值基本信息
        String productId = UUIDUtils.create();
        priceValueOrg.setId(productId);
        priceValueOrg.setVersionId(newVersion.getId());
        priceValueOrg.setPid(batchMap.get(productItem.getBatchId()+"&"+productItem.getBatchNum()));
        priceValueOrg.setType(OrgTypeEunm.ORG_PRODUCT.getKey());
        priceValueOrg.setOrgId("");
        priceValueOrg.setOrgCode(dicMap.get(productItem.getProductTypeNum()).getChildCode());
        priceValueOrg.setOrgName(dicMap.get(productItem.getProductTypeNum()).getChildName());

        //赋值楼栋计划信息
        priceValueOrg.setPanoBatchSaleArea(productItem.getTotalSaleArea());
        priceValueOrg.setPanoTotalRoomNum(productItem.getTotalRoomNum());
        priceValueOrg.setPanoTotalSaleArea(productItem.getTotalSaleArea());
        priceValueOrg.setPanoBatchRoomNum(productItem.getBatchRoomNum());
        priceValueOrg.setPanoBatchSaleArea(productItem.getBatchSaleArea());
        priceValueOrg.setPanoSalePark(productItem.getSalePark());
        priceValueOrg.setPanoTotalBuildArea(productItem.getTotalBuildArea());
        priceValueOrg.setPanoBatchBuildArea(productItem.getBatchBuildArea());

        //赋值属性标签信息
        if(StringUtils.isNotEmpty(productItem.getSaleNum()) && StringUtils.isNotEmpty(productItem.getSaleType())){
            priceValueOrg.setBusinessType(productItem.getSaleNum());
            priceValueOrg.setBusinessTypeName(productItem.getSaleType());
        }else{
            throw new MsgException(CodeEnum.NON_EXISTENT_BUSINESSTYPE);
        }
        if(StringUtils.isNotEmpty(productItem.getDecorateNum()) && StringUtils.isNotEmpty(productItem.getDecorateName())){
            priceValueOrg.setFreeType(productItem.getDecorateNum());
            priceValueOrg.setFreeTypeName(productItem.getDecorateName());
        }else{
            throw new MsgException(CodeEnum.NON_EXISTENT_FREETYPE);
        }
        if(StringUtils.isNotEmpty(productItem.getProTypeCode()) && StringUtils.isNotEmpty(productItem.getProType())){
            priceValueOrg.setProType(productItem.getProTypeCode());
            priceValueOrg.setProTypeName(productItem.getProType());
        }else{
            throw new MsgException(CodeEnum.NON_EXISTENT_PROTYPE);
        }
        priceValueOrg.setProductCode(productItem.getProductTypeNum());
        priceValueOrg.setProductType(productItem.getProductTypeName());
        priceValueOrg.setProProductCode(dicMap.get(productItem.getProductTypeNum()).getParentCode());
        priceValueOrg.setProProductType(dicMap.get(productItem.getProductTypeNum()).getParentName());

        //匹配时间节点
        priceValueOrg.setOpenTime(openTimeMap.get(productItem.getId()));
        priceValueOrg.setOpenTimeActual(openTimeActualMap.get(productItem.getId()));
        priceValueOrg.setAdvanceSaleTime(advanceSaleTimeMap.get(productItem.getId()));
        priceValueOrg.setAdvanceSaleTimeActual(advanceSaleTimeActualMap.get(productItem.getId()));
        priceValueOrg.setSupplyTime(supplyTimeMap.get(productItem.getId()));
        priceValueOrg.setSupplyTimeActual(supplyTimeActualMap.get(productItem.getId()));
        priceValueOrg.setSupplyTimeVirtual(supplyTimeVirtualMap.get(productItem.getId()));
        priceValueOrg.setOpenSaleTime(openSaleTimeMap.get(productItem.getId()));
        priceValueOrg.setOpenSaleTimeActual(openSaleTimeActualMap.get(productItem.getId()));
        priceValueOrg.setCappingTime(cappingTimeMap.get(productItem.getId()));
        priceValueOrg.setCappingTimeActual(cappingTimeActualMap.get(productItem.getId()));
        priceValueOrg.setCompletedTime(completedTimeMap.get(productItem.getId()));
        priceValueOrg.setCompletedTimeActual(completedTimeActualMap.get(productItem.getId()));
        priceValueOrg.setCarryOverTime(carryOverTimeMap.get(productItem.getId()));
        priceValueOrg.setCarryOverTimeActual(carryOverTimeActualMap.get(productItem.getId()));
        priceValueOrg.setActualDeliveryTime(actualDeliveryTimeMap.get(productItem.getId()));
        priceValueOrg.setActualDeliveryTimeActual(actualDeliveryTimeActualMap.get(productItem.getId()));
        priceValueOrg.setContractDeliveryTime(contractDeliveryTimeMap.get(productItem.getId()));
        priceValueOrg.setContractDeliveryTimeActual(contractDeliveryTimeActualMap.get(productItem.getId()));

        //赋值货值信息
        priceValueOrg.setNum(productItem.getBatchRoomNum());
        if(isParkList.contains(productItem.getProductTypeNum())){
            priceValueOrg.setIsParking(IsDeleteEnum.YES.getKey());
            priceValueOrg.setParkingNum(productItem.getBatchRoomNum());
        }else{
            priceValueOrg.setIsParking(IsDeleteEnum.NO.getKey());
            priceValueOrg.setRoomNum(productItem.getBatchRoomNum());
        }
        priceValueOrg.setIsSplit(IsDeleteEnum.NO.getKey());
        priceValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
        priceValueOrg.setCreateTime(now);
        priceValueOrg.setUpdateTime(now);

        Integer batchRoomNum = productItem.getBatchRoomNum();
        priceValueOrg.setNum(batchRoomNum);

        BigDecimal saleArea = productItem.getBatchSaleArea() == null ? new BigDecimal(0) : productItem.getBatchSaleArea();
        priceValueOrg.setSaleArea(saleArea);

        priceValueOrg.setTotalNum(batchRoomNum);
        priceValueOrg.setTotalSaleArea(saleArea);

        if(productItem.getSaleNum().equals(SalyTypeEnum.SALABLE.getKey())
                || productItem.getSaleNum().equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey())){
            if (batchRoomNum <= 0){
                String message =  "产品构成信息不完整:"+productItem.getProductTypeName()+"套数/个数小于等于0";
                CodeEnum.NON_PANOPLAN_PRODUT.setMessage(message);
                throw new MsgException(CodeEnum.NON_PANOPLAN_PRODUT);
            }

            if (saleArea.compareTo(new BigDecimal(0)) <= 0){
                if (!isParkList.contains(productItem.getProductTypeNum())){
                    String message = "产品构成信息不完整:"+productItem.getProductTypeName()+"面积小于等于0";
                    CodeEnum.NON_PANOPLAN_PRODUT.setMessage(message);
                    throw new MsgException(CodeEnum.NON_PANOPLAN_PRODUT);
                }
            }
        }

        return priceValueOrg;
    }

    /**
     * 投资版分期有可售或阶段性自持产品构成校验
     */
    private void investmentStageSelfVerification(PanoPlanCastDecisionBO panoPlanCastDecisionBO, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap) {
        //分期有可售或阶段性自持产品构成没有批次或供货日期时，不允许新建该分期投资版价格版本
        List<PanoplanBuildPlanItem> productItems = panoPlanCastDecisionBO.getProductItems();
        for (int i = 0; i < productItems.size(); i++) {
            PanoplanBuildPlanItem panoplanBuildPlanItem = productItems.get(i);
            String saleNum = panoplanBuildPlanItem.getSaleNum();
            if (StringUtils.isNotEmpty(saleNum) && (saleNum.equals(SalyTypeEnum.SALABLE.getKey())
                    || saleNum.equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey()))) {
                LocalDateTime supplyTime = supplyTimeMap.get(panoplanBuildPlanItem.getId());
                LocalDateTime supplyActualTime = supplyTimeActualMap.get(panoplanBuildPlanItem.getId());
                LocalDateTime supplyVirtualTime = supplyTimeVirtualMap.get(panoplanBuildPlanItem.getId());
                if (supplyTime == null && supplyActualTime == null && supplyVirtualTime == null) {
                    throw new MsgException(CodeEnum.NON_PANO_TIME);
                }
            }
        }
    }

    /**
     * 投资版创建校验信息
     */
    private void investmentCreateVersionVerification(String projectFid, String createType, MdmStage mdmStage, List<String> stageIds) {
        //项目下存在待提交审批、审批中、审批被驳回的版本，不允许新建版本
        List<PriceVersion> approvalStates = priceVersionMapper.selectApprovalStateByStagesIds(stageIds, Arrays.asList(VersionStatusEnum.EXAMINEDAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey(), VersionStatusEnum.FAILUREAPPROVED.getKey()), IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(approvalStates)){
            throw new MsgException(CodeEnum.EXIST_APPROVAL_PROJECT_VERSIONS);
        }

        //分期存在待编制、编制中、待提交审批、审批中、审批已驳回的投资版价格版本，不允许新建该分期投资版价格版本
        List<String> existVersionTypes = Arrays.asList(VersionTypeEunm.INVESTMENT.getKey(),VersionTypeEunm.WARPLAN.getKey(),VersionTypeEunm.GETPRICE.getKey(),VersionTypeEunm.DYNAMIC.getKey());
        List<String> existVersionStates =  Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(),
                VersionStatusEnum.ORGANIZATION.getKey(), VersionStatusEnum.EXAMINEDAPPROVED.getKey(),
                VersionStatusEnum.APPROVED.getKey(),VersionStatusEnum.FAILUREAPPROVED.getKey() );
        List<PriceVersion> priceExistCDVersions = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(projectFid, existVersionTypes, existVersionStates, IsDeleteEnum.NO.getKey());
        if(CollectionUtils.isNotEmpty(priceExistCDVersions)){
            throw new MsgException(CodeEnum.EXIST_APPROVAL_CASTDECISION_VERSIONS);
        }

        //如果分期下没有投资版货值,不受规则（分期战规版、大定价版、动态版价格存在一个审批通过版本时，不允许新建该分期投资版价格版本）
        List<String> cdVersionStates = Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(),VersionStatusEnum.ORGANIZATION.getKey(),VersionStatusEnum.EXAMINEDAPPROVED.getKey(),VersionStatusEnum.APPROVED.getKey(),VersionStatusEnum.FAILUREAPPROVED.getKey(),VersionStatusEnum.SUCCESSAPPROVED.getKey());
        List<PriceVersion> priceCDVersions = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(projectFid, Arrays.asList(VersionTypeEunm.INVESTMENT.getKey()), cdVersionStates, IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(priceCDVersions)){
            //异常创建版本去掉此验证
            if (!createType.equals(VersionCreateEnum.EXCEPTIONCREATE.getKey())){
                //分期战规版、大定价版、动态版价格存在一个审批通过版本时，不允许新建该分期投资版价格版本
                List<String> versionTypes = Arrays.asList(VersionTypeEunm.WARPLAN.getKey(), VersionTypeEunm.GETPRICE.getKey(), VersionTypeEunm.DYNAMIC.getKey());
                List<String> versionStates =  Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey());
                List<PriceVersion> priceOtherVersions = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(projectFid, versionTypes, versionStates, IsDeleteEnum.NO.getKey());
                if(CollectionUtils.isNotEmpty(priceOtherVersions)){
                    throw new MsgException(CodeEnum.EXIST_APPROVAL_VERSIONS);
                }
            }
        }
    }

    /**
     * 版本日志
     */
    private void priceVersionLogInfo(String createType, String instId, LocalDateTime now, MdmStage mdmStage, PriceVersion newVersion, String createBy) {
        try {
            versionLogService.saveVersionLogInfo(mdmStage.getProjectId(), mdmStage.getProjectFid(), ModuleTypeEunm.PRICE.getKey(), newVersion.getVersionCreateState().equals(VersionCreateEnum.MANUALCREATE.getKey()) ? VersionEventEnum.MANUALCREATE.getKey() : VersionEventEnum.SYS_GENERATE.getKey(),
                    newVersion.getId(), VersionNameUtils.getVersionName(newVersion), null,
                    newVersion.getVersionState(), createType.equals(VersionCreateEnum.MANUALCREATE.getKey()) ? "" : "1", instId, createBy, now, "货值创建版本", null, IsDeleteEnum.NO.getKey(), createBy, now);
        } catch (Exception e) {
            logger.error("################ create price version versionLog error : " + e);
        }
    }

    /**
     *  货值投资版代办信息
     */
    private void priceInvestmentNoticeInfo(String projectFid, IdmUser createUser, LocalDateTime now, PriceVersion newVersion) {
        try {
            //查询代办信息
            if (newVersion.getVersionCreateState().equals(VersionCreateEnum.MANUALCREATE.getKey())){
                List<SysNotice> notices = sysNoticeService.selectModeByProjectFidAndVersionType(projectFid, ModuleTypeEunm.PRICE.getKey(), VersionTypeEunm.INVESTMENT.getKey(), ProcessingStateEnum.UNTREATED.getKey(), IsDeleteEnum.NO.getKey());
                if(CollectionUtils.isNotEmpty(notices)){
                    for(SysNotice notice : notices){
                        notice.setState(ProcessingStateEnum.PROCESSED.getKey());
                        notice.setProcessingTime(now);
                        notice.setUpdateTime(now);
                        notice.setHandlePerson(Constants.SYS);
                        notice.setUpdateBy(Constants.SYS);
                        sysNoticeMapper.updateById(notice);
                        String instanceId = notice.getPortalInstanceId();
                        //门户代办消息待办转已办
                        if(StringUtils.isNotEmpty(instanceId)){
                            commonService.updatePortalProcess(instanceId, OperatorTypeEnum.TRANSFERRED_TO_OFFICE.getKey(), createUser, null);
                        }
                    }
                }
            }
        }catch (Exception e){
            logger.error("################ create price version notice error : "+e);
        }
    }

    /**
     * 分期操盘方式
     * @param mdmStage 分期
     * @return
     */
    private String getStagePartnerToMarket(MdmStage mdmStage) {
        //项目操盘方式
        //DULICP=独立操盘-------营销操盘
        //LIANHECP=联合操盘-------非营销操盘
        //BUCP=不操盘-------非营销操盘
        String market = null;
        StagePartNers partner = stagePartNersService.getStagePartnersByProjectFid(mdmStage.getProjectFid());
        if (partner != null) {
            String isOpMarketing = partner.getIsOpMarketing();
            if (StringUtils.isNotEmpty(isOpMarketing) && (MarketingEunm.LIANHECP.getValue().equals(isOpMarketing) || MarketingEunm.BUCP.getValue().equals(isOpMarketing))) {
                market = MarketingEunm.IS_NOT_MARKET.getKey();
            } else if (StringUtils.isNotEmpty(isOpMarketing) && MarketingEunm.DULICP.getValue().equals(isOpMarketing)) {
                market = MarketingEunm.IS_MARKET.getKey();
            } else {
                throw new MsgException(CodeEnum.NON_MARKET_ERROR);
            }
        } else {
            throw new MsgException(CodeEnum.NON_MARKET_ERROR);
        }
        return market;
    }

    /**
     *  创建货值投资版信息
     */
    private PriceVersion createInvestmentVersionInfo(PriceVersion oldPriceVersion, String oldVersionId, String oldVersionNum,
                                                     MdmStage mdmStage, String createType, IdmUser createUser, Integer lable,
                                                     PanoPlanCastDecisionBO panoPlanCastDecisionBO, String market, LocalDateTime now) {
        String newVersionId = UUIDUtils.create();
        PriceVersion newVersion = new PriceVersion();
        String newVersionNum = "";
        if(oldPriceVersion != null){
            oldVersionId = oldPriceVersion.getId();
            newVersionNum = VersionUtils.bigVersionInc(oldPriceVersion.getVersionNum());
            newVersion.setPreVersionId(oldPriceVersion.getId());
            newVersion.setPreVersionNum(oldPriceVersion.getVersionNum());
            newVersion.setIsAssessmentVersion(IsDeleteEnum.NO.getKey());
        }else{//第一次创建版本
            newVersionNum = VersionUtils.bigVersionInc("");
            newVersion.setPreVersionId("");
            newVersion.setPreVersionNum("");
            newVersion.setIsAssessmentVersion(IsDeleteEnum.YES.getKey());
        }

        newVersion.setPreVersionId(oldVersionId);
        newVersion.setPreVersionNum(oldVersionNum);
        newVersion.setId(newVersionId);
        newVersion.setProjectId(mdmStage.getProjectId());
        newVersion.setProjectfId(mdmStage.getProjectFid());
        newVersion.setStageName(mdmStage.getStageName());
        newVersion.setStageCode(mdmStage.getStageCode());
        newVersion.setVersionName(VersionTypeEunm.INVESTMENT.getValue()+newVersionNum);
        newVersion.setVersionNum(newVersionNum);
        newVersion.setVersionType(VersionTypeEunm.INVESTMENT.getKey());
        newVersion.setVersionCreateState(createType);
        newVersion.setCreateBy(createUser.getAlias());
        if (createType.equals(VersionCreateEnum.MANUALCREATE.getKey()) ||
                createType.equals(VersionCreateEnum.EXCEPTIONCREATE.getKey())){
            newVersion.setVersionState(VersionStatusEnum.NOTPREPARED.getKey());
        }else{
            newVersion.setVersionState(VersionStatusEnum.SYSGENERATION.getKey());
        }

        if(lable != null && lable.equals(1)){
            newVersion.setRemake("自动生成");
        }else if(lable != null && lable.equals(2)){
            newVersion.setRemake("手动待办生成");
        }else{
            newVersion.setRemake("手动创建");
        }

        newVersion.setSourcePlan(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
        newVersion.setSourcePlanDetail("["+DateUtils.dateToString(LocalDateTimeUtils.convertLDTToDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate()) ,
                DateUtils.DATE_KEY_SMALL_STR) + "]-[" +  panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType() +"]-[" +
                panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion()+"]");
        newVersion.setSourceValue(oldVersionId);
        newVersion.setSourcePanoVersionType(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType());
        newVersion.setSourcePanoPlanVersion(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());
        newVersion.setSourcePanoCreatedDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate());
        newVersion.setIsMarket(market);
        newVersion.setIsDelete(IsDeleteEnum.NO.getKey());
        newVersion.setCreateTime(now);
        newVersion.setUpdateTime(now);
        newVersion.setAscriptionDate(now.toLocalDate());

        return newVersion;
    }

    /**
     * 保存投资版货值信息
     */
    @Transactional
    private void saveInvestmentValueInfo(PriceVersion newVersion, List<PriceValueOrg> parkingList, List<PriceValueOrg> productInsertList, List<PriceValueOrg> batchInsertList, List<PriceValueOrg> groupInsertList, List<PriceValueOrg> projectList) {
        if(newVersion != null){
            priceVersionMapper.insert(newVersion);
        }
        priceValueOrgMapper.insertBatch(projectList);
        priceValueOrgMapper.insertBatch(groupInsertList);
        priceValueOrgMapper.insertBatch(batchInsertList);
        if(CollectionUtils.isNotEmpty(productInsertList)){
            priceValueOrgMapper.insertBatch(productInsertList);
        }
        if(CollectionUtils.isNotEmpty(parkingList)){
            priceValueOrgMapper.insertBatch(parkingList);
        }
    }
    
    /**
     * 归集明源面积段
     */
    public Map<String, Map> myCollectHouse(String projectFid, String kingdeeProjectfId, List<String> parkingBuildLis, Map<String, BigDecimal> preBuildAvPriceMap, LocalDateTime now,LocalDateTime ModifiedTime) {
        Map<String, Map> resultMap = new HashMap<>();
        //根据分期id查询（明源）房间信息流水表
        List<MymRooms> rooms = mymRoomsService.selectNewestWarPlanByFid(projectFid);
        //查询签约信息
        Map<String, MymContractDto> qyMap = new HashMap<>();
        List<MymContractDto> mymContractDtos = dmOdsMyVsMarsSContractService.selectNewestContractsByProjectFid(kingdeeProjectfId);
        if(ModifiedTime != null) {
        	mymContractDtos = mymContractDtos.stream().filter(s-> s.getYwgsDate().isBefore(ModifiedTime)).collect(Collectors.toList());
        }
        if(CollectionUtils.isNotEmpty(mymContractDtos)){
            for (MymContractDto mymContractDto : mymContractDtos){
                qyMap.put(mymContractDto.getRoomGUID().toLowerCase(), mymContractDto);
            }
        }

        //楼栋下总套数和面积
        Map<String, BigDecimal> areaMap = new HashMap<>();//楼栋下总面积
        Map<String, Integer> numMap = new HashMap<>();//楼栋下总套数

        //楼栋下已定价金额和面积,用于计算已售均价
        Map<String, BigDecimal> pricedPriceMap = new HashMap<>();//楼栋下已定价
        Map<String, BigDecimal> pricedAreaMap = new HashMap<>();//楼栋下总套数

        //合并成为新房源记录
        List<MyRoomBO> taotalRoomBOS = new ArrayList<MyRoomBO>();
        if(CollectionUtils.isNotEmpty(rooms)){
            for (MymRooms room : rooms){
                //房源id
                String roomGuid = room.getRoomGUID().toLowerCase();
                //楼栋id
                String bldPrdId = room.getBldPrdId();

                MyRoomBO roomBO = new MyRoomBO();
                roomBO.setRoomGuid(roomGuid);
                roomBO.setBldPrdId(bldPrdId);
                roomBO.setIsSoldOrPriced(null);
                if(room.getxIszc() != null && room.getxIszc().equals(IsDeleteEnum.YES.getKey())){//是自持
                    roomBO.setIsZc(IsDeleteEnum.YES.getKey());
                }else{
                    roomBO.setIsZc(IsDeleteEnum.NO.getKey());
                }

                //实测建筑面积, sc=实测 ,ys=预售 ,bld=楼栋
                //如果实测建筑面积为空,取预售建筑面积
                BigDecimal scBldArea = room.getScBldArea()==null?new BigDecimal(0):room.getScBldArea();
                BigDecimal ysBldArea = room.getYsBldArea()==null?new BigDecimal(0):room.getYsBldArea();
                if(scBldArea != null && scBldArea.compareTo(new BigDecimal(0)) > 0){
                    roomBO.setRoomSaleArea(scBldArea);//实测建筑面积
                }else{
                    roomBO.setRoomSaleArea(ysBldArea);//预售建筑面积
                }

                BigDecimal djTotal = room.getDjTotal()==null?new BigDecimal(0):room.getDjTotal();
                BigDecimal total = room.getTotal()==null?new BigDecimal(0):room.getTotal();
                if (djTotal != null && djTotal.compareTo(new BigDecimal(0)) > 0){
                    roomBO.setIsSoldOrPriced(IsDeleteEnum.NO.getKey());
                    roomBO.setRoomPrice(djTotal);
                }else if (total != null && total.compareTo(new BigDecimal(0)) > 0){
                    roomBO.setIsSoldOrPriced(IsDeleteEnum.NO.getKey());
                    roomBO.setRoomPrice(total);
                }

                //查看房源是否签约,房源是签约状态但是没有业绩归属日期，则不算签约房源
                MymContractDto mymContractDto = qyMap.get(roomGuid);
                if(mymContractDto !=  null){
                    roomBO.setIsSoldOrPriced(IsDeleteEnum.YES.getKey());

                    BigDecimal cjRmbTotal = mymContractDto.getCjRmbTotal()==null?new BigDecimal(0):mymContractDto.getCjRmbTotal();
                    if (cjRmbTotal != null && cjRmbTotal.compareTo(new BigDecimal(0)) > 0){
                        roomBO.setRoomPrice(cjRmbTotal);
                        roomBO.setRoomSaleArea(mymContractDto.getBldArea());
                    }

                    //判断补差日期，是否添加补差金额和面积
                    LocalDateTime auditDate = mymContractDto.getAuditDate();
                    if(auditDate != null){
                        roomBO.setRoomPrice(BigDecimalADD(roomBO.getRoomPrice(), mymContractDto.getBcTotal()));
                        roomBO.setRoomSaleArea(BigDecimalADD(roomBO.getRoomSaleArea(), mymContractDto.getBcArea()));
                    }

                    qyMap.remove(roomGuid);
                }

                //获取这个房间的楼栋面积
                BigDecimal totalRoomSaleArea = areaMap.get(bldPrdId);//总可售面积
                if(totalRoomSaleArea != null){
                    //有数据后,每次的楼栋面积相加
                    totalRoomSaleArea = BigDecimalADD(totalRoomSaleArea, roomBO.getRoomSaleArea());
                }else{
                    //第一次是=实测建筑面积or预售建筑面积
                    totalRoomSaleArea = roomBO.getRoomSaleArea();
                }
                //把楼栋的总可售面积放到这个楼栋下面
                areaMap.put(room.getBldPrdId(), totalRoomSaleArea);

                //获取这个房间的楼栋数量 第一次进来是1,第二次++
                Integer totalRoomNum = numMap.get(bldPrdId);
                if (totalRoomNum != null){
                    totalRoomNum ++;
                }else{
                    totalRoomNum = 1;
                }
                //最后放到这个楼栋总套数map里面去
                numMap.put(room.getBldPrdId(), totalRoomNum);

                //如果房源是已定价的，则添加
                if (roomBO.getRoomPrice() != null && roomBO.getRoomPrice().compareTo(new BigDecimal(0)) > 0){
                    BigDecimal price = pricedPriceMap.get(roomBO.getBldPrdId());
                    pricedPriceMap.put(roomBO.getBldPrdId(),BigDecimalADD(price, roomBO.getRoomPrice()));

                    BigDecimal area = pricedAreaMap.get(roomBO.getBldPrdId());
                    pricedAreaMap.put(roomBO.getBldPrdId(), BigDecimalADD(area, roomBO.getRoomSaleArea()));
                }

                taotalRoomBOS.add(roomBO);
            }
        }

        //如果有签约记录但是没有房源，也添加一条记录
        if (CollectionUtils.isNotEmpty(qyMap)){
            for(Map.Entry<String, MymContractDto> mymContractDtoMap : qyMap.entrySet()){
                MymContractDto mymContractDto = mymContractDtoMap.getValue();
                //房源id
                String roomGUID = mymContractDto.getRoomGUID();

                //楼栋id
                String bldPrdId = mymContractDto.getBldPrdID().toLowerCase();

                MyRoomBO roomBO = new MyRoomBO();
                roomBO.setRoomGuid(roomGUID);
                roomBO.setBldPrdId(bldPrdId);
                roomBO.setIsSoldOrPriced(IsDeleteEnum.YES.getKey());
                roomBO.setIsZc(IsDeleteEnum.NO.getKey());

                BigDecimal cjRmbTotal = mymContractDto.getCjRmbTotal()==null?new BigDecimal(0):mymContractDto.getCjRmbTotal();
                if (cjRmbTotal != null && cjRmbTotal.compareTo(new BigDecimal(0)) > 0){
                    roomBO.setRoomPrice(cjRmbTotal);
                    roomBO.setRoomSaleArea(mymContractDto.getBldArea());
                }

                //判断补差日期，是否添加补差金额和面积
                LocalDateTime auditDate = mymContractDto.getAuditDate();
                if(auditDate != null){
                    roomBO.setRoomPrice(BigDecimalADD(roomBO.getRoomPrice(), mymContractDto.getBcTotal()));
                    roomBO.setRoomSaleArea(BigDecimalADD(roomBO.getRoomSaleArea(), mymContractDto.getBcArea()));
                }

                //获取这个房间的楼栋面积
                BigDecimal totalRoomSaleArea = areaMap.get(bldPrdId);//总可售面积
                if(totalRoomSaleArea != null){
                    //有数据后,每次的楼栋面积相加
                    totalRoomSaleArea = BigDecimalADD(totalRoomSaleArea, roomBO.getRoomSaleArea());
                }else{
                    //第一次是=实测建筑面积or预售建筑面积
                    totalRoomSaleArea = roomBO.getRoomSaleArea();
                }
                //把楼栋的总可售面积放到这个楼栋下面
                areaMap.put(bldPrdId, totalRoomSaleArea);

                //获取这个房间的楼栋数量 第一次进来是1,第二次++
                Integer totalRoomNum = numMap.get(bldPrdId);
                if (totalRoomNum != null){
                    totalRoomNum ++;
                }else{
                    totalRoomNum = 1;
                }
                //最后放到这个楼栋总套数map里面去
                numMap.put(bldPrdId, totalRoomNum);

                //如果房源是已定价的，则添加
                if (roomBO.getRoomPrice() != null && roomBO.getRoomPrice().compareTo(new BigDecimal(0)) > 0){
                    BigDecimal price = pricedPriceMap.get(roomBO.getBldPrdId());
                    pricedPriceMap.put(roomBO.getBldPrdId(),BigDecimalADD(price, roomBO.getRoomPrice()));

                    BigDecimal area = pricedAreaMap.get(roomBO.getBldPrdId());
                    pricedAreaMap.put(roomBO.getBldPrdId(), BigDecimalADD(area, roomBO.getRoomSaleArea()));
                }

                taotalRoomBOS.add(roomBO);
            }
        }

        //判断房源是否已定价，如果不是，则计算货值。判断车位是否已定价，如果没有，则刨除计算
        List<MyRoomBO> saleRoomBOS = new ArrayList<MyRoomBO>();
        if(CollectionUtils.isNotEmpty(taotalRoomBOS)){
            for (MyRoomBO roomBO : taotalRoomBOS){
                String bldPrdId = roomBO.getBldPrdId();
                BigDecimal averagePrice = new BigDecimal(0);

                BigDecimal preAveragePrice = preBuildAvPriceMap.get(bldPrdId);
                if(preAveragePrice != null){
                    averagePrice = preAveragePrice;
                }else{
                    BigDecimal totalSalePrice = pricedPriceMap.get(bldPrdId);
                    BigDecimal totalSaleArea = pricedAreaMap.get(bldPrdId);

                    averagePrice = bigDecimalDIV(totalSalePrice, totalSaleArea);
                }

                //判断是否是车位还是房源(房间)
                if(parkingBuildLis.contains(bldPrdId)){//是车位
                    BigDecimal roomPrice = roomBO.getRoomPrice();

                    //归集已售和已定价车位
                    if(roomPrice != null && roomPrice.compareTo(new BigDecimal(0)) > 0){
                        saleRoomBOS.add(roomBO);
                    }
                }else{
                    BigDecimal roomPrice = roomBO.getRoomPrice();

                    //判断是否已定价房源
                    if(roomPrice != null && roomPrice.compareTo(new BigDecimal(0)) > 0){
                        saleRoomBOS.add(roomBO);
                    }else{
                        BigDecimal roomSaleArea = roomBO.getRoomSaleArea();
                        BigDecimal price = BigDecimalMUL(roomSaleArea, averagePrice);
                        roomBO.setRoomPrice(price);

                        saleRoomBOS.add(roomBO);
                    }
                }
            }
        }

        //查询面积段信息
        List<SysDictionary> codes = sysDictionaryService.selectDictionaryByType(Arrays.asList("area_segmenta"));

        //可售信息
        Map<String, PriceValueOrg> soldParkingMap = new HashMap<String, PriceValueOrg>();//已售车位
        Map<String, PriceValueOrg> notSoldParkingOrgMap = new HashMap<String, PriceValueOrg>();//已定价未售车位
        Map<String, Map<String, PriceValueOrg>> houseOrgMap = new HashMap<String, Map<String, PriceValueOrg>>();//已售面积段

        //自持信息
        Map<String, Integer> zcParkingNumMap = new HashMap<>();//楼栋下自持房源套数
        Map<String, BigDecimal> zcParkingPriceMap = new HashMap<>();//楼栋下自持房源面积

        if(CollectionUtils.isNotEmpty(saleRoomBOS)){
            for (MyRoomBO roomBO : saleRoomBOS){
                String bldPrdId = roomBO.getBldPrdId();
                Integer isSoldOrPriced = roomBO.getIsSoldOrPriced();
               
                Integer isZc = roomBO.getIsZc();
                BigDecimal roomSaleArea = roomBO.getRoomSaleArea();
                BigDecimal roomPrice = roomBO.getRoomPrice();

                //判断是否是车位还是房源(房间)
                if(parkingBuildLis.contains(bldPrdId)){//车位

                    //是自持车位
                    if(isZc != null && isZc.equals(IsDeleteEnum.YES.getKey())){
                        Integer zcNum = zcParkingNumMap.get(bldPrdId);
                        if (zcNum != null){
                            zcNum ++;
                        }else{
                            zcNum = 1;
                        }
                        zcParkingNumMap.put(bldPrdId, zcNum);

                        BigDecimal zcParkingPrice = zcParkingPriceMap.get(bldPrdId);
                        if(roomPrice != null){
                            zcParkingPrice = BigDecimalADD(zcParkingPrice, roomPrice);
                        }else{
                            zcParkingPrice = roomPrice;
                        }
                        zcParkingPriceMap.put(bldPrdId, zcParkingPrice);

                        continue;
                    }

                    //归集已售和已定价车位
                    if(roomBO.getRoomPrice() != null && roomBO.getRoomPrice().compareTo(new BigDecimal(0)) > 0){
                        if(isSoldOrPriced != null && isSoldOrPriced.equals(IsDeleteEnum.NO.getKey())){//已定价未售
                            //获取已定价未售车位中是否存在这个车位楼栋id信息
                            PriceValueOrg org = notSoldParkingOrgMap.get(bldPrdId);
                            if(org != null){
                                Integer num = org.getNum();
                                num++;
                                //如果车位存在 车位数+1
                                org.setNum(num);
                                org.setParkingNum(num);
                                org.setParkingPriced(num);
                                BigDecimal price = BigDecimalADD(org.getPrice(), roomPrice);
                                //把每次的底价总价相加就是最终的底价总价
                                org.setPrice(price);
                                org.setPricePriced(price);
                                org.setNotCommodityValue(price);
                                //均价=总的底价总价/总的车位数;
                                org.setAveragePriceParking(bigDecimalDIV(price, new BigDecimal(num)));
                            }else{
                                org = new PriceValueOrg();
                                org.setId(UUIDUtils.create());
                                //房源 组团 分期 楼栋 车位 类型信息
                                org.setType(OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey());
                                org.setOrgCode(OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey());
                                org.setOrgName(OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getValue());
                                //是否已售(0.否 1.是),当前是未售=否
                                org.setIsSale(IsDeleteEnum.NO.getKey());
                                //套数/车位数,当前是车位那么就是车位数 第一次进来默认1
                                org.setNum(1);
                                org.setParkingNum(1);
                                org.setParkingPriced(1);
                                //底价总价
                                org.setPrice(roomPrice);
                                org.setPricePriced(roomPrice);
                                org.setNotCommodityValue(roomPrice);
                                //均价=总的底价总价/总的车位数;第一次进来就是/1=本身
                                org.setAveragePriceParking(roomPrice);
                                org.setIsParking(IsDeleteEnum.YES.getKey());
                                org.setIsSplit(IsSplitEnum.NO.getKey());
                                org.setIsDelete(IsDeleteEnum.NO.getKey());
                                org.setCreateTime(now);
                                org.setUpdateTime(now);
                            }
                            //最后把当前的楼栋Id和版本详细放到 ,已定价未售车位map中
                            notSoldParkingOrgMap.put(bldPrdId, org);
                        }else if(isSoldOrPriced != null && isSoldOrPriced.equals(IsDeleteEnum.YES.getKey())) {//已定价已售车位
                            PriceValueOrg org = soldParkingMap.get(bldPrdId);
                            if(org != null){
                                //存在车位数+1
                                Integer num = org.getNum();
                                num++;
                                org.setNum(num);
                                org.setParkingNum(num);
                                org.setParkingSold(num);
                                BigDecimal price = BigDecimalADD(org.getPrice(), roomPrice);
                                org.setPrice(price);
                                org.setPriceSold(price);
                                org.setNotCommodityValue(price);
                                org.setAveragePriceParking(bigDecimalDIV(price, new BigDecimal(num)));
                            }else{
                                //第一次进来
                                org = new PriceValueOrg();
                                org.setId(UUIDUtils.create());
                                org.setType(OrgTypeEunm.ORG_SALE_PACKAGE.getKey());
                                org.setOrgCode(OrgTypeEunm.ORG_SALE_PACKAGE.getKey());
                                org.setOrgName(OrgTypeEunm.ORG_SALE_PACKAGE.getValue());
                                org.setIsSale(IsDeleteEnum.YES.getKey());
                                org.setNum(1);
                                org.setParkingNum(1);
                                org.setParkingSold(1);
                                org.setPrice(roomPrice);
                                org.setPriceSold(roomPrice);
                                org.setNotCommodityValue(roomPrice);
                                org.setAveragePriceParking(roomPrice);
                                org.setIsParking(IsDeleteEnum.YES.getKey());
                                org.setIsSplit(IsSplitEnum.NO.getKey());
                                org.setIsDelete(IsDeleteEnum.NO.getKey());
                                org.setCreateTime(now);
                                org.setUpdateTime(now);
                            }
                            soldParkingMap.put(bldPrdId, org);
                        }
                    }
                }else{//面积段
                    for(SysDictionary dic : codes){
                        String dictValue = dic.getDictValue();
                        String dictName = dic.getDictName();

                        String[] split = dictValue.split("-");
                        Integer start = Integer.valueOf(split[0]);
                        Integer end = Integer.valueOf(split[1]);
                        if(roomSaleArea.compareTo(new BigDecimal(start)) >= 0 && roomSaleArea.compareTo(new BigDecimal(end)) < 0){

                            Map<String, PriceValueOrg> priceValueOrgMap = houseOrgMap.get(bldPrdId);
                            if(CollectionUtils.isNotEmpty(priceValueOrgMap)){
                                PriceValueOrg priceValueOrg = priceValueOrgMap.get(dictValue);
                                if (priceValueOrg != null){
                                    if(isZc == 0){
                                        //套数
                                        Integer roomNum = priceValueOrg.getNum()==null?0:priceValueOrg.getNum();
                                        roomNum++;
                                        priceValueOrg.setNum(roomNum);
                                        priceValueOrg.setRoomNum(roomNum);

                                        //面积
                                        priceValueOrg.setSaleArea(BigDecimalADD(priceValueOrg.getSaleArea(), roomSaleArea));

                                        //货值
                                        BigDecimal price = BigDecimalADD(priceValueOrg.getPrice(), roomPrice);
                                        priceValueOrg.setPrice(price);
                                        priceValueOrg.setHouseCommodityValue(price);
                                        priceValueOrg.setAveragePriceHouse(bigDecimalDIV(price, priceValueOrg.getSaleArea()));

                                        //是否已售
                                        if(isSoldOrPriced != null && isSoldOrPriced .equals(IsDeleteEnum.YES.getKey())){
                                            priceValueOrg.setPriceSold(BigDecimalADD(priceValueOrg.getPriceSold(), roomPrice));
                                            priceValueOrg.setAreaSold(BigDecimalADD(priceValueOrg.getAreaSold(), roomSaleArea));
                                            priceValueOrg.setRoomSold(1+(priceValueOrg.getRoomSold()==null?0:priceValueOrg.getRoomSold()));
                                        }else if(isSoldOrPriced != null && isSoldOrPriced.equals(IsDeleteEnum.NO.getKey())){
                                            priceValueOrg.setPricePriced(BigDecimalADD(priceValueOrg.getPricePriced(), roomPrice));
                                            priceValueOrg.setAreaPriced(BigDecimalADD(priceValueOrg.getAreaPriced(), roomSaleArea));
                                            priceValueOrg.setRoomPriced(1+(priceValueOrg.getRoomPriced()==null?0:priceValueOrg.getRoomPriced()));
                                        }
                                    }else{
                                        //套数
                                        Integer roomZcNum = priceValueOrg.getRoomZc()==null?0:priceValueOrg.getRoomZc();
                                        roomZcNum++;
                                        priceValueOrg.setRoomZc(roomZcNum);

                                        //面积
                                        priceValueOrg.setAreaZc(BigDecimalADD(priceValueOrg.getAreaZc(), roomSaleArea));

                                        //货值
                                        BigDecimal zcPrice = BigDecimalADD(priceValueOrg.getPriceRoomZc(), roomPrice);
                                        priceValueOrg.setPriceRoomZc(zcPrice);
                                    }

                                    //总套数
                                    Integer roomTotalNum = priceValueOrg.getTotalNum()==null?0:priceValueOrg.getTotalNum();
                                    roomTotalNum++;
                                    priceValueOrg.setTotalNum(roomTotalNum);

                                    //总面积
                                    priceValueOrg.setTotalSaleArea(BigDecimalADD(priceValueOrg.getTotalSaleArea(), roomSaleArea));

                                    //把对应的这个面积段的实体放进map
                                    priceValueOrgMap.put(dictValue, priceValueOrg);
                                }else{
                                    priceValueOrg = new PriceValueOrg();

                                    createFristNotSaleAreaPartOrg(priceValueOrg, now, isSoldOrPriced, roomPrice, roomSaleArea, dictValue, dictName, isZc);

                                    priceValueOrgMap.put(dictValue, priceValueOrg);
                                }
                            }else{
                                priceValueOrgMap = new HashMap<String, PriceValueOrg>();
                                PriceValueOrg priceValueOrg = new PriceValueOrg();

                                createFristNotSaleAreaPartOrg(priceValueOrg, now, isSoldOrPriced, roomPrice, roomSaleArea, dictValue, dictName, isZc);

                                priceValueOrgMap.put(dictValue, priceValueOrg);
                            }
                            houseOrgMap.put(bldPrdId, priceValueOrgMap);
                            break;
                        }
                    }
                }
            }
        }

        resultMap.put("soldParkingMap", soldParkingMap);
        resultMap.put("notSoldParkingOrgMap", notSoldParkingOrgMap);
        resultMap.put("houseOrgMap", houseOrgMap);
        resultMap.put("areaMap", areaMap);
        resultMap.put("numMap", numMap);
        resultMap.put("zcParkingNumMap", zcParkingNumMap);
        resultMap.put("zcParkingPriceMap", zcParkingPriceMap);

        return resultMap;
    }

    /**
     *  创建一定加面积段信息
     */
    private PriceValueOrg createFristNotSaleAreaPartOrg(PriceValueOrg priceValueOrg, LocalDateTime now, Integer isSoldOrPriced, BigDecimal roomPrice, BigDecimal roomSaleArea, String dictValue, String dictName, int isZc) {

        priceValueOrg.setId(UUIDUtils.create());
        priceValueOrg.setType(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey());

        //面积段信息
        priceValueOrg.setAreaPart(dictValue);
        priceValueOrg.setOrgName(dictName);
        priceValueOrg.setOrgCode(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey());

        //总数
        priceValueOrg.setTotalNum(1);
        priceValueOrg.setTotalSaleArea(roomSaleArea);

        if(isZc == 0){
            priceValueOrg.setNum(1);
            priceValueOrg.setRoomNum(1);
            priceValueOrg.setSaleArea(roomSaleArea);
            priceValueOrg.setPrice(roomPrice);
            priceValueOrg.setHouseCommodityValue(roomPrice);
            priceValueOrg.setAveragePriceHouse(bigDecimalDIV(priceValueOrg.getPrice(), priceValueOrg.getSaleArea()));

            if(isSoldOrPriced != null && isSoldOrPriced.equals(IsDeleteEnum.YES.getKey())){
                priceValueOrg.setPriceSold(roomPrice);
                priceValueOrg.setAreaSold(roomSaleArea);
                priceValueOrg.setRoomSold(1);
            }else if (isSoldOrPriced != null && isSoldOrPriced.equals(IsDeleteEnum.NO.getKey())){
                priceValueOrg.setPricePriced(roomPrice);
                priceValueOrg.setAreaPriced(roomSaleArea);
                priceValueOrg.setRoomPriced(1);
            }
        }else{
            priceValueOrg.setRoomZc(1);
            priceValueOrg.setAreaZc(roomSaleArea);
            priceValueOrg.setPriceRoomZc(roomPrice);
        }

        priceValueOrg.setIsSplit(IsSplitEnum.NO.getKey());
        priceValueOrg.setIsParking(IsDeleteEnum.NO.getKey());
        priceValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
        priceValueOrg.setCreateTime(now);
        priceValueOrg.setUpdateTime(now);
        return priceValueOrg;
    }

    /**
     * 方法描述：将double转成BigDecimal向除
     * @param money 被除数
     * @param price 除数
     * 创建人：yang
     * 创建时间：2017年3月15日 下午3:13:03
     */
    public BigDecimal bigDecimalDIV(BigDecimal money, BigDecimal price) {

        if(null == money || null == price){
            return BigDecimal.ZERO;
        }

        if((price.compareTo(new BigDecimal(0)) == 0)){
            return BigDecimal.ZERO;
        }

        BigDecimal b1 = money.setScale(4, BigDecimal.ROUND_HALF_UP);
        BigDecimal b2 = price.setScale(4, BigDecimal.ROUND_HALF_UP);
        BigDecimal doubleValue = b1.divide(b2, 4, RoundingMode.HALF_UP);

        return doubleValue;
    }

    /**
     * 方法描述：将double转成BigDecimal向乘
     * @param money 被乘数
     * @param price 乘数
     * 创建人：yang
     * 创建时间：2017年3月15日 下午3:13:03
     */
    public BigDecimal BigDecimalMUL(BigDecimal money, BigDecimal price) {
        if(null == money || null == price){
            return new BigDecimal(0);
        }

        BigDecimal b1 = money.setScale(4, BigDecimal.ROUND_HALF_UP);
        BigDecimal b2 = price.setScale(4, BigDecimal.ROUND_HALF_UP);
        BigDecimal doubleValue = b1.multiply(b2).setScale(4, BigDecimal.ROUND_HALF_UP);

        return doubleValue;
    }

    /**
     * 方法描述：将double转成BigDecimal向加
     * @param money 被加数
     * @param price 加数
     * 创建人：yang
     * 创建时间：2017年3月15日 下午3:13:03
     */
    public BigDecimal BigDecimalADD(BigDecimal money, BigDecimal price) {

        if(money != null && price != null){
            BigDecimal b1 = money.setScale(4, BigDecimal.ROUND_HALF_UP);
            BigDecimal b2 = price.setScale(4, BigDecimal.ROUND_HALF_UP);
            BigDecimal doubleValue = b1.add(b2).setScale(4, BigDecimal.ROUND_HALF_UP);
            return doubleValue;
        }else if(null == money && null == price){
            return new BigDecimal(0);
        }else if (money != null && null == price){
            return money;
        }else{
            return price;
        }
    }

    /**
     * 楼栋计划投资版货值变更
     * @param projectFid 分期id
     * @return  List<PriceValueCompareVO> 货值版本变动信息
     */
    @Override
    @Transactional
    public List<PriceValueCompareVO> panoCastDecisionVersionChange(String projectFid, String instId) {
        LocalDateTime now = LocalDateTime.now();
        //查询分期信息
        MdmStage mdmStage = stageService.selectById(projectFid);

        //查询项目信息
        MdmProject mdmProject = projectService.selectByProjectId(mdmStage.getProjectId(), IsDeleteEnum.NO.getKey());

        //获取最新的投资版楼栋计划
        PanoPlanCastDecisionBO panoPlanCastDecisionBO = panoplanBuildPlanService.selectNewestByFid(projectFid, Arrays.asList(VersionTypeEunm.INVESTMENT.getValue()), IsDeleteEnum.NO.getKey());

        PriceVersion priceVersion = priceVersionMapper.selectNewestVersionByFidAndTypes(projectFid, Arrays.asList(VersionTypeEunm.INVESTMENT.getKey()),
                Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(), VersionStatusEnum.ORGANIZATION.getKey(), VersionStatusEnum.EXAMINEDAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey()
                        , VersionStatusEnum.FAILUREAPPROVED.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
        if (priceVersion != null){
            String versionState = priceVersion.getVersionState();
            String priceVersionId = priceVersion.getId();
            String versionType = priceVersion.getVersionType();

            //将节点为取预售证时间的存储在指定Map中
            Map<String, LocalDateTime> openTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> openTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> advanceSaleTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> advanceSaleTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> supplyTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> supplyTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> openSaleTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> openSaleTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> cappingTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> cappingTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> completedTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> completedTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> carryOverTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> carryOverTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> actualDeliveryTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> actualDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> contractDeliveryTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> contractDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
            List<PanoplanBuildPlanItemDetail> timeDetails = panoPlanCastDecisionBO.getDetails();
            if(CollectionUtils.isNotEmpty(timeDetails)){
                for (PanoplanBuildPlanItemDetail timeDetail : timeDetails){
                    String pkId = timeDetail.getPkId();
                    String nodeCode = timeDetail.getNodeCode();
                    if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00002.getKey())){
                        openTimeMap.put(pkId, timeDetail.getPlannedFinishDate());
                        openTimeActualMap.put(pkId, timeDetail.getActualFinishDate());
                    }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00001.getKey())){
                        advanceSaleTimeMap.put(pkId, timeDetail.getPlannedFinishDate());
                        advanceSaleTimeActualMap.put(pkId, timeDetail.getActualFinishDate());
                    }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00002.getKey())){
                        supplyTimeMap.put(pkId, timeDetail.getPlannedFinishDate());
                        supplyTimeActualMap.put(pkId, timeDetail.getActualFinishDate());
                    }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00003.getKey())){
                        openSaleTimeMap.put(pkId, timeDetail.getPlannedFinishDate());
                        openSaleTimeActualMap.put(pkId, timeDetail.getActualFinishDate());
                    }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00003.getKey())){
                        cappingTimeMap.put(pkId, timeDetail.getPlannedFinishDate());
                        cappingTimeActualMap.put(pkId, timeDetail.getActualFinishDate());
                    }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00004.getKey())){
                        completedTimeMap.put(pkId, timeDetail.getPlannedFinishDate());
                        completedTimeActualMap.put(pkId, timeDetail.getActualFinishDate());
                    }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00006.getKey())){
                        carryOverTimeMap.put(pkId, timeDetail.getPlannedFinishDate());
                        carryOverTimeActualMap.put(pkId, timeDetail.getActualFinishDate());
                    }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00005.getKey())){
                        actualDeliveryTimeMap.put(pkId, timeDetail.getPlannedFinishDate());
                        actualDeliveryTimeActualMap.put(pkId, timeDetail.getActualFinishDate());
                    }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.NODE_000.getKey())){
                        contractDeliveryTimeMap.put(pkId, timeDetail.getPlannedFinishDate());
                        contractDeliveryTimeActualMap.put(pkId, timeDetail.getActualFinishDate());
                    }
                }
            }

            //货值业态信息
            Map<String, PriceValueCastDecisionEXTBO> produceMap = new HashMap<String, PriceValueCastDecisionEXTBO>();
            Map<String, PriceValueCastDecisionEXTBO> valueProduceMap = new HashMap<String, PriceValueCastDecisionEXTBO>();
            List<PriceValueCastDecisionEXTBO> productOrgs = priceValueOrgMapper.selectProductByVersionId(priceVersion.getId(), OrgTypeEunm.ORG_PRODUCT.getKey(), IsDeleteEnum.NO.getKey());
            for (PriceValueCastDecisionEXTBO productOrg : productOrgs){
                String code = productOrg.getGroupId()+"&"+productOrg.getBatchCode()+"&"+productOrg.getProductCode()+"&"+productOrg.getFreeTypeName()+"&"+productOrg.getBusinessTypeName()+"&"+productOrg.getProTypeName();
                valueProduceMap.put(code ,productOrg);
                produceMap.put(code ,productOrg);
            }

            //楼栋计划业态信息
            //对比产品构成
            boolean isSupplyToTime = false;
            Map<String, String> timePkIdMap = new HashMap<String, String>();
            List<PriceValueCompareVO> compareVOList = new ArrayList<PriceValueCompareVO>();
            List<PanoplanBuildPlanItem> productItems = panoPlanCastDecisionBO.getProductItems();
            for (PanoplanBuildPlanItem productItem : productItems){

                //封装时间MAP
                String code = productItem.getBatchId()+"&"+productItem.getBatchNum()+"&"+productItem.getProductTypeNum()+"&"+productItem.getDecorateName()+"&"+productItem.getSaleType()+"&"+productItem.getProType();
                String itemId = productItem.getId();
                timePkIdMap.put(code, itemId);

                //开始对比
                PriceValueCompareVO compareVO = new PriceValueCompareVO();
                compareVO.setId(UUIDUtils.create());
                compareVO.setCode(productItem.getBatchId() + "&" + productItem.getBatchNum());
                compareVO.setName(productItem.getProductTypeName());
                compareVO.setType(OrgTypeEunm.ORG_PRODUCT.getKey());

                if (isParkList.contains(productItem.getProductTypeNum())){
                    compareVO.setIsParking(IsDeleteEnum.YES.getKey());
                }else{
                    compareVO.setIsParking(IsDeleteEnum.NO.getKey());
                }

                PriceValueOrg valueProductOrg = valueProduceMap.get(code);
                if(valueProductOrg != null){

                    if(!productItem.getDecorateNum().equals(valueProductOrg.getFreeType())){
                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailVOList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                        detailVO.setChangeType(Constants.FREE_TYPE_CHANGE);
                        detailVO.setChangeDetail(valueProductOrg.getFreeTypeName()+"变为"+productItem.getDecorateName());
                        detailVOList.add(detailVO);

                        compareVO.setDetailList(detailVOList);
                    }

                    if(!productItem.getSaleNum().equals(valueProductOrg.getBusinessType())){
                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = compareVO.getDetailList();
                        if(CollectionUtils.isEmpty(detailList)){
                            detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        }
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                        detailVO.setChangeType(Constants.BUSINESS_TYPE_CHANGE);
                        detailVO.setChangeDetail(valueProductOrg.getBusinessTypeName()+"变为"+productItem.getSaleType());
                        detailList.add(detailVO);

                        compareVO.setDetailList(detailList);
                    }

                    if(!productItem.getProTypeCode().equals(valueProductOrg.getProType())){
                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = compareVO.getDetailList();
                        if(CollectionUtils.isEmpty(detailList)){
                            detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        }
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                        detailVO.setChangeType(Constants.PRO_TYPE_CHANGE);
                        detailVO.setChangeDetail(valueProductOrg.getProTypeName()+"变为"+productItem.getProType());
                        detailList.add(detailVO);

                        compareVO.setDetailList(detailList);
                    }

                    Integer batchRoomNum = productItem.getBatchRoomNum()==null?0:productItem.getBatchRoomNum();
                    Integer roomNum = valueProductOrg.getNum()==null?0:valueProductOrg.getNum();
                    if(!batchRoomNum.equals(roomNum)){
                        Integer subNum = batchRoomNum - roomNum;

                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = compareVO.getDetailList();
                        if(CollectionUtils.isEmpty(detailList)){
                            detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        }
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                        detailVO.setChangeType(Constants.NUM_CHANGE);
                        if(subNum > 0){
                            detailVO.setChangeDetail(Constants.ADD_NUM_CHANGE+Math.abs(subNum));
                        }else{
                            detailVO.setChangeDetail(Constants.REDUCE_NUM_CHANGE+Math.abs(subNum));
                        }
                        detailList.add(detailVO);

                        compareVO.setDetailList(detailList);
                    }

                    if (!isParkList.contains(productItem.getProductTypeNum())){
                        BigDecimal batchSaleArea = productItem.getBatchSaleArea()==null?new BigDecimal(0):productItem.getBatchSaleArea();
                        BigDecimal saleArea = valueProductOrg.getSaleArea()==null?new BigDecimal(0):valueProductOrg.getSaleArea();
                        if(!batchSaleArea.equals(saleArea)){
                            BigDecimal subArea = StrUtils.BigDecimalSub(batchSaleArea, saleArea);

                            List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = compareVO.getDetailList();
                            if(CollectionUtils.isEmpty(detailList)){
                                detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                            }
                            PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                            detailVO.setChangeType(Constants.AREA_CHANGE);
                            if(subArea.compareTo(new BigDecimal(0)) > 0){
                                detailVO.setChangeDetail(Constants.ADD_AREA_CHANGE+subArea.abs());
                            }else{
                                detailVO.setChangeDetail(Constants.REDUCE_AREA_CHANGE+subArea.abs());
                            }
                            detailList.add(detailVO);

                            compareVO.setDetailList(detailList);
                        }
                    }

                    //对比产品构成取得预售许可证节点的计划日期
                    LocalDateTime supplyTime = supplyTimeMap.get(itemId);
                    if(supplyTime != null && valueProductOrg.getSupplyTime() != null &&
                            supplyTime.compareTo(valueProductOrg.getSupplyTime()) != 0){
                        isSupplyToTime = true;
                    }else if(supplyTime == null && valueProductOrg.getSupplyTime() != null){
                        isSupplyToTime = true;
                    }else if (supplyTime != null && valueProductOrg.getSupplyTime() == null){
                        isSupplyToTime = true;
                    }

                    List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = compareVO.getDetailList();
                    if(CollectionUtils.isNotEmpty(detailList)){

                        compareVO.setChangeBeforeNum(valueProductOrg.getNum());
                        compareVO.setChangeAfterNum(productItem.getBatchRoomNum());

                        if (!isParkList.contains(productItem.getProductTypeNum())){
                            compareVO.setChangeBeforeArea(valueProductOrg.getSaleArea());
                            compareVO.setChangeAfterArea(productItem.getBatchSaleArea());
                        }

                        compareVOList.add(compareVO);
                    }
                }else{
                    List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = compareVO.getDetailList();
                    if(CollectionUtils.isEmpty(detailList)){
                        detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                    }
                    PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                    detailVO.setChangeType(Constants.ADD_PRODUCT_TYPE);
                    detailVO.setChangeDetail(Constants.ADD_PRODUCT_DETAIL+productItem.getProductTypeName());
                    detailList.add(detailVO);
                    compareVO.setDetailList(detailList);

                    compareVO.setChangeAfterNum(productItem.getBatchRoomNum());
                    if (!isParkList.contains(productItem.getProductTypeNum())) {
                        compareVO.setChangeAfterArea(productItem.getBatchSaleArea());
                    }

                    compareVOList.add(compareVO);
                }

                //处理时间
                openTimeMap.put(code, openTimeMap.get(itemId));
                supplyTimeMap.put(code, supplyTimeMap.get(itemId));
                supplyTimeActualMap.put(code, supplyTimeActualMap.get(itemId));
                advanceSaleTimeMap.put(code, advanceSaleTimeMap.get(itemId));
                openSaleTimeMap.put(code, openSaleTimeMap.get(itemId));
                cappingTimeMap.put(code, cappingTimeMap.get(itemId));
                completedTimeMap.put(code, completedTimeMap.get(itemId));
                carryOverTimeMap.put(code, carryOverTimeMap.get(itemId));
                actualDeliveryTimeMap.put(code, actualDeliveryTimeMap.get(itemId));
                contractDeliveryTimeMap.put(code, contractDeliveryTimeMap.get(itemId));

                valueProduceMap.remove(code);
            }

            if(CollectionUtils.isNotEmpty(valueProduceMap)){
                for (Map.Entry<String, PriceValueCastDecisionEXTBO> orgMap :valueProduceMap.entrySet()){
                    PriceValueCastDecisionEXTBO org = orgMap.getValue();

                    PriceValueCompareVO compareVO = new PriceValueCompareVO();
                    compareVO.setId(UUIDUtils.create());
                    compareVO.setCode(org.getGroupId()+"&"+org.getBatchCode());
                    compareVO.setType(OrgTypeEunm.ORG_PRODUCT.getKey());
                    compareVO.setName(org.getProductType());

                    compareVO.setChangeBeforeNum(org.getNum());
                    if (isParkList.contains(org.getProductCode())){
                        compareVO.setIsParking(IsDeleteEnum.YES.getKey());
                    }else{
                        compareVO.setIsParking(IsDeleteEnum.NO.getKey());
                        compareVO.setChangeBeforeArea(org.getSaleArea());
                    }

                    List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = compareVO.getDetailList();
                    if(CollectionUtils.isEmpty(detailList)){
                        detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                    }
                    PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                    detailVO.setChangeType(Constants.DELETE_PRODUCT_TYPE);
                    detailVO.setChangeDetail(Constants.DELETE_PRODUCT_DETAIL);
                    detailList.add(detailVO);
                    compareVO.setDetailList(detailList);

                    compareVOList.add(compareVO);
                }
            }

            //设置系统用户
            IdmUser idmUser = new IdmUser();
            idmUser.setAlias(Constants.SYS);
            idmUser.setUsercn(Constants.SYS_NAME);

            //查看楼栋计划和货值产品构成是否有变化,如果没有则时间节点直接刷新
            if (CollectionUtils.isEmpty(compareVOList)){
                //当前版本是否被签约使用,如果当前投资版被签约使用，自动生成新版本
                Map<String, Boolean> signMap = signPlanVersionService.priceBoolean(Arrays.asList(priceVersion.getId()));
                Boolean isSign = signMap.get(priceVersion.getId());
                if (isSign){
                    try{
                        String versionId = createSysCastDecisionVersion(projectFid, VersionCreateEnum.AUTOMATICCREATE.getKey(), idmUser, null, instId);
                        supplyPlanVersionService.createSupplyPlanVersion(versionId, VersionTypeEunm.INVESTMENT.getKey(), Constants.SYS);
                    }catch (Exception e){
                        logger.error("###############   panoCastDecisionVersionChange  createSysCastDecisionVersion  error:"+e.getMessage(), e);
                    }
                }else{
                    LocalDate ascriptionDate = priceVersion.getAscriptionDate();
                    int ascripyear = ascriptionDate.getYear();
                    Month ascripmonth = ascriptionDate.getMonth();
                    int year = now.getYear();
                    Month month = now.getMonth();
                    //未被签约使用，且是当月版本，直接刷新
                    if(year == ascripyear && ascripmonth.equals(month)){
                        if (CollectionUtils.isEmpty(compareVOList)){
                            //刷新楼栋计划时间节点信息
                            investmentRefreshTimeNode(now, panoPlanCastDecisionBO, priceVersion, versionState, priceVersionId, versionType, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, produceMap, timePkIdMap, instId);
                        }else {
                            //查看货值版本状态
                            //除去审批中、审批通过直接刷新
                            if (versionState.equals(VersionStatusEnum.NOTPREPARED.getKey())
                                    || versionState.equals(VersionStatusEnum.ORGANIZATION.getKey())
                                    || versionState.equals(VersionStatusEnum.EXAMINEDAPPROVED.getKey())
                                    || versionState.equals(VersionStatusEnum.FAILUREAPPROVED.getKey())){

                                //刷新楼栋计划
                                investmentRefreshInfo(priceVersion, panoPlanCastDecisionBO, instId);
                            }else if (versionState.equals(VersionStatusEnum.APPROVED.getKey()) || versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())) {
                                //审批中、审批通过需要生成代办
                                try{
                                    noticeInvestmentCreateAndHandle(projectFid, mdmStage, mdmProject, panoPlanCastDecisionBO, ProcessingModeEnum.MANUAL.getKey(), ProcessingStateEnum.UNTREATED.getKey());
                                }catch (Exception e){
                                    logger.error("######################     投资版审批中、审批通过货值代办错误："+e.getMessage(), e);
                                }
                            }
                        }
                    }else{
                        try{
                            String versionId = createSysCastDecisionVersion(projectFid, VersionCreateEnum.AUTOMATICCREATE.getKey(), idmUser, null, instId);
                            supplyPlanVersionService.createSupplyPlanVersion(versionId, VersionTypeEunm.INVESTMENT.getKey(), Constants.SYS);
                        }catch (Exception e){
                            logger.error("###############   panoCastDecisionVersionChange  createSysCastDecisionVersion  error:"+e.getMessage(), e);
                        }
                    }
                }
            }else{
                noticeInvestmentCreateAndHandle(projectFid, mdmStage, mdmProject, panoPlanCastDecisionBO, ProcessingModeEnum.MANUAL.getKey(), ProcessingStateEnum.UNTREATED.getKey());
            }
        }else{
            noticeInvestmentCreateAndHandle(projectFid, mdmStage, mdmProject, panoPlanCastDecisionBO, ProcessingModeEnum.MANUAL.getKey(), ProcessingStateEnum.UNTREATED.getKey());
        }
        return null;
    }

    /**
     *  投资版刷新
     */
    private void investmentRefreshInfo(PriceVersion priceVersion, PanoPlanCastDecisionBO panoPlanCastDecisionBO, String instId) {
        LocalDateTime now = LocalDateTime.now();

        String versionId = priceVersion.getId();
        String projectfId = priceVersion.getProjectfId();

        //查询指定分期信息
        MdmStage mdmStage = stageService.selectById(projectfId);
        if(mdmStage == null){
            throw new MsgException(CodeEnum.STAGE_NON_EXISTENT);
        }

        PriceVersionBackups priceVersionBackups = new PriceVersionBackups();
        BeanUtils.copyProperties(priceVersion, priceVersionBackups);
        priceVersionBackups.setVersionId(priceVersion.getId());
        priceVersionBackups.setId(UUIDUtils.create());

        //修改货值使用的楼栋计划版本信息
        priceVersion.setSourcePanoVersionType(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType());
        priceVersion.setSourcePanoPlanVersion(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());
        priceVersion.setSourcePanoCreatedDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate());

        priceVersion.setSourcePlan(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
        priceVersion.setSourcePlanDetail("["+ DateUtils.dateToString(LocalDateTimeUtils.convertLDTToDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate()) ,
                DateUtils.DATE_KEY_SMALL_STR) + "]-[" +  panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType() +"]-[" +
                panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion()+"]");
        priceVersion.setRemake("楼栋计划刷新");
        priceVersion.setUpdateTime(now);
        priceVersion.setUpdateBy(Constants.SYS);
        priceVersion.setVersionState(VersionStatusEnum.NOTPREPARED.getKey());
        if(priceVersion.getVersionState().equals(VersionStatusEnum.ORGANIZATION.getKey())){
            priceVersion.setVersionState(VersionStatusEnum.NOTPREPARED.getKey());
        }

        //将节点为取预售证时间的存储在指定Map中
        Map<String, LocalDateTime> openTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeVirtualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        List<PanoplanBuildPlanItemDetail> details = panoPlanCastDecisionBO.getDetails();
        if(CollectionUtils.isNotEmpty(details)){
            for (int i = 0;i < details.size(); i++){
                castDecisionTimeItemMapInfo(openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, details, i);
            }
        }

        //分期有可售或阶段性自持产品构成校验
        investmentStageSelfVerification(panoPlanCastDecisionBO, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap);

        //查询最新审批通过的价格管理投资版
        Map<String, PriceValueCastDecisionAllOrgEXTBO> preProductMap = new HashMap<String, PriceValueCastDecisionAllOrgEXTBO>();
        Map<String, PriceValueCastDecisionAllOrgEXTBO> preParkingMap = new HashMap<String, PriceValueCastDecisionAllOrgEXTBO>();
        Map<String, PriceValueCastDecisionAllOrgEXTBO> preNotSaleParkingMap = new HashMap<String, PriceValueCastDecisionAllOrgEXTBO>();
        //获取上版本产品构成以及可售车位和待售车位数据
        List<PriceValueCastDecisionAllOrgEXTBO> prePriceValueOrgList = priceValueOrgMapper.selectCastDecisionAllOrg(versionId, IsDeleteEnum.NO.getKey());
        for (PriceValueCastDecisionAllOrgEXTBO preOrg : prePriceValueOrgList) {
            castDecisionPreOrgInfo(preProductMap, preParkingMap, preNotSaleParkingMap, preOrg);
        }

        //创建分期
        PriceValueOrg projectOrg = createStageValueInfo(now, mdmStage, versionId);

        //创建组团
        Map<String, PriceValueOrg> groupInsertMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> groupMap = new HashMap<String, PriceValueOrg>();
        List<PanoplanBuildPlanItem> groupItems = panoPlanCastDecisionBO.getGroupItems();
        for(PanoplanBuildPlanItem groupItem : groupItems){
            castDecisionGroupItemInfo(now, projectOrg, groupInsertMap, groupMap, groupItem, versionId);
        }

        //创建批次
        Map<String, PriceValueOrg> batchInsertMap = new HashMap<String, PriceValueOrg>();
        Map<String, String> batchMap = new HashMap<String, String>();
        List<PanoplanBuildPlanItem> batchItems = panoPlanCastDecisionBO.getBatchItems();
        for(PanoplanBuildPlanItem batchItem : batchItems) {
            castDecisionBatchItemInfo(now, versionId, groupMap, batchInsertMap, batchMap, batchItem);
        }

        //构建product
        Map<String, PriceValueOrg> productMap = new HashMap<String, PriceValueOrg>();
        List<PanoplanBuildPlanItem> pproductItems = panoPlanCastDecisionBO.getProductItems();

        //找上级分类
        castDecisionProductItemToDic(priceVersion, now, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, batchMap, productMap, pproductItems);

        List<PriceValueOrg> productList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> parkingList = new ArrayList<PriceValueOrg>();
        for (Map.Entry<String, PriceValueOrg> productmap : productMap.entrySet()) {
            castDecisionProductInsertInfo(priceVersion, preProductMap, productList, parkingList, productmap);
        }

        //货值汇总
        List<PriceValueOrg> productInsertList = new ArrayList<PriceValueOrg>();
        for (PriceValueOrg productOrg : productList){
            castDecisionProductSumInfo(batchInsertMap, productInsertList, productOrg);
        }

        List<PriceValueOrg> batchInsertList = new ArrayList<PriceValueOrg>();
        if (CollectionUtils.isNotEmpty(batchInsertMap)) {
            castDecisionBatchSumInfo(groupInsertMap, batchInsertMap, batchInsertList);
        }

        List<PriceValueOrg> groupInsertList = new ArrayList<PriceValueOrg>();
        if (CollectionUtils.isNotEmpty(groupInsertMap)){
            castDecisionGroupSumInfo(projectOrg, groupInsertMap, groupInsertList);
        }

        List<PriceValueOrg> projectList = Arrays.asList(projectOrg);
        saveInvestmentRefreshInfo(priceVersion, parkingList, productInsertList, batchInsertList, groupInsertList, projectList);

        saveVersionBackups(priceVersion, priceVersionBackups, now);

        priceRefreshVersionLogInfo(priceVersion, instId, now, "货值上游变动刷新版本:楼栋计划变更", "#############     investmentRefreshInfo    saveVersionBackups    error:");
    }

    private void castDecisionPreOrgInfo(Map<String, PriceValueCastDecisionAllOrgEXTBO> preProductMap, Map<String, PriceValueCastDecisionAllOrgEXTBO> preParkingMap, Map<String, PriceValueCastDecisionAllOrgEXTBO> preNotSaleParkingMap, PriceValueCastDecisionAllOrgEXTBO preOrg) {
        String type = preOrg.getType();
        if (type.equals(OrgTypeEunm.ORG_SALING_PARKING.getKey())) {
            preParkingMap.put(preOrg.getCode(), preOrg);
        } else if (type.equals(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())) {
            preNotSaleParkingMap.put(preOrg.getCode(), preOrg);
        } else {
            preProductMap.put(preOrg.getCode(), preOrg);
        }
    }

    private void castDecisionProductItemToDic(PriceVersion priceVersion, LocalDateTime now, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, Map<String, String> batchMap, Map<String, PriceValueOrg> productMap, List<PanoplanBuildPlanItem> pproductItems) {
        Map<String, DictionaryCodeBO> dicMap = getPanoProductDictionary(pproductItems);

        List<PriceValueOrg> notSalyTypeList = new ArrayList<PriceValueOrg>();
        for (PanoplanBuildPlanItem productItem : pproductItems) {
            castDecisionProductItemInfo(now, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, priceVersion, batchMap, productMap, dicMap, notSalyTypeList, productItem);
        }
    }

    private void castDecisionBatchSumInfo(Map<String, PriceValueOrg> groupInsertMap, Map<String, PriceValueOrg> batchInsertMap, List<PriceValueOrg> batchInsertList) {
        for (Map.Entry<String, PriceValueOrg> batchOrgMap : batchInsertMap.entrySet()) {

            PriceValueOrg batchOrg = batchOrgMap.getValue();
            PriceValueOrg groupOrg = groupInsertMap.get(batchOrg.getPid());
            valueUpSummary(groupOrg, batchOrg);
            groupInsertMap.put(batchOrg.getPid(), groupOrg);

            batchInsertList.add(batchOrg);
        }
    }

    private void castDecisionProductInsertInfo(PriceVersion priceVersion, Map<String, PriceValueCastDecisionAllOrgEXTBO> preProductMap, List<PriceValueOrg> productList, List<PriceValueOrg> parkingList, Map.Entry<String, PriceValueOrg> productmap) {
        String code = productmap.getKey();
        PriceValueOrg productOrg = productmap.getValue();
        Integer productOrgNum = productOrg.getNum();
        String orgCode = productOrg.getOrgCode();
        String businessType = productOrg.getBusinessType();

        //如果产品构成是 不可租售 或 可租，则不复制车位信息
        if (businessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()) || businessType.equals(SalyTypeEnum.RENTED.getKey())) {
            productList.add(productOrg);
            return;
        }

        productOrg = calculationInvestmentProductValueInfo(productOrg, code, preProductMap, orgCode, productOrgNum, priceVersion, parkingList);

        productList.add(productOrg);
    }

    private void castDecisionBatchItemInfo(LocalDateTime now, String versionId, Map<String, PriceValueOrg> groupMap, Map<String, PriceValueOrg> batchInsertMap, Map<String, String> batchMap, PanoplanBuildPlanItem batchItem) {
        PriceValueOrg priceValueOrg = createInvestmentBatchValueInfo(now, versionId, groupMap.get(batchItem.getBatchId()), batchItem);

        batchInsertMap.put(priceValueOrg.getId(), priceValueOrg);
        batchMap.put(batchItem.getBatchId() + "&" + batchItem.getBatchNum(), priceValueOrg.getId());
    }

    /**
     *  货值版本刷新日志
     */
    private void priceRefreshVersionLogInfo(PriceVersion priceVersion, String instId, LocalDateTime now, String s, String s2) {
        try {
            versionLogService.saveVersionLogInfo(priceVersion.getProjectId(), priceVersion.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), VersionEventEnum.SYS_REFRESH.getKey(), priceVersion.getId(), VersionNameUtils.getVersionName(priceVersion), priceVersion.getVersionState(),
                    priceVersion.getVersionState(), "1", instId, Constants.SYS, now, s, null, IsDeleteEnum.NO.getKey(), Constants.SYS, now);
        } catch (Exception e) {
            logger.error(s2 + e.getMessage(), e);
        }
    }

    /**
     *  查找上级分类
     */
    private Map<String, DictionaryCodeBO> getPanoProductDictionary(List<PanoplanBuildPlanItem> pproductItems) {
        Map<String, DictionaryCodeBO> dicMap = new HashMap<>();
        List<String> productCodes = Optional.of(pproductItems).orElseGet(ArrayList::new)
                .stream().map(PanoplanBuildPlanItem::getProductTypeNum)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(productCodes)) {
            List<DictionaryCodeBO> dicType = sysDictionaryService.selectByCodes(productCodes);
            if (CollectionUtils.isNotEmpty(dicType)) {
                for (DictionaryCodeBO bo : dicType) {
                    dicMap.put(bo.getChildCode(), bo);
                }
            }
        }
        return dicMap;
    }

    @Transactional
    private void saveVersionBackups(PriceVersion priceVersion, PriceVersionBackups priceVersionBackups, LocalDateTime now) {
        try{
            List<PriceValueOrgBackups> orgBackups = new ArrayList<PriceValueOrgBackups>();
            QueryWrapper<PriceValueOrg> orgWrapper = new QueryWrapper<PriceValueOrg>();
            orgWrapper.eq("version_id", priceVersion.getId())
                    .eq("is_delete", IsDeleteEnum.NO.getKey());
            List<PriceValueOrg> orgList = priceValueOrgMapper.selectList(orgWrapper);
            if (CollectionUtils.isNotEmpty(orgList)){
                for (PriceValueOrg org : orgList){
                    PriceValueOrgBackups newOrg = new PriceValueOrgBackups();
                    BeanUtils.copyProperties(org, newOrg);
                    newOrg.setId(UUIDUtils.create());
                    newOrg.setBackupsId(org.getId());
                    newOrg.setBackupsVersionId(priceVersionBackups.getId());
                    newOrg.setUpdateTime(now);
                    orgBackups.add(newOrg);
                }
            }
            //保存备份信息
            priceVersionBackupsService.save(priceVersionBackups);
            priceValueOrgBackupsService.saveBatch(orgBackups);

        }catch (Exception e){
            logger.error("#############     investmentRefreshInfo    saveVersionBackups    error:"+e.getMessage(), e);
        }
    }

    /**
     *  保存投资版货值信息
     */
    @Transactional
    private void saveInvestmentRefreshInfo(PriceVersion priceVersion, List<PriceValueOrg> parkingList, List<PriceValueOrg> productInsertList, List<PriceValueOrg> batchInsertList,
                                           List<PriceValueOrg> groupInsertList, List<PriceValueOrg> projectList) {
        try{
            QueryWrapper<PriceValueOrg> orgWrapper = new QueryWrapper<PriceValueOrg>();
            orgWrapper.eq("version_id", priceVersion.getId()).eq("is_delete", IsDeleteEnum.NO.getKey());
            //删除之前货值信息
            priceVersionMapper.updateByPrimaryKeySelective(priceVersion);
            priceValueOrgMapper.delete(orgWrapper);

            priceValueOrgMapper.insertBatch(projectList);
            priceValueOrgMapper.insertBatch(groupInsertList);
            priceValueOrgMapper.insertBatch(batchInsertList);
            if(CollectionUtils.isNotEmpty(productInsertList)){
                priceValueOrgMapper.insertBatch(productInsertList);
            }
            if(CollectionUtils.isNotEmpty(parkingList)){
                priceValueOrgMapper.insertBatch(parkingList);
            }
        }catch (Exception e){
            logger.error("#############     investmentRefreshInfo    saveInvestmentRefreshInfo   error:"+e.getMessage(), e);
        }
    }

    /**
     * 投资版刷新时间节点
     */
    private void investmentRefreshTimeNode(LocalDateTime now, PanoPlanCastDecisionBO panoPlanCastDecisionBO, PriceVersion priceVersion, String versionState, String priceVersionId, String versionType, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, Map<String, PriceValueCastDecisionEXTBO> produceMap, Map<String, String> timePkIdMap, String instId) {
        priceVersion.setSourcePanoVersionType(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType());
        priceVersion.setSourcePanoPlanVersion(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());
        priceVersion.setSourcePanoCreatedDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate());

        priceVersion.setSourcePlan(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
        priceVersion.setSourcePlanDetail("["+ DateUtils.dateToString(LocalDateTimeUtils.convertLDTToDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate()) ,
                DateUtils.DATE_KEY_SMALL_STR) + "]-[" +  panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType() +"]-[" +
                panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion()+"]");
        priceVersion.setRemake("楼栋计划时间节点刷新");
        priceVersion.setUpdateTime(now);
        priceVersion.setUpdateBy(Constants.SYS);
        priceVersionMapper.updateByPrimaryKeySelective(priceVersion);

        //更新楼栋计划时间
        List<PriceValueOrg> updateTimeOrgList = new ArrayList<>();
        for (Map.Entry<String, PriceValueCastDecisionEXTBO> valueProducts : produceMap.entrySet()){
            PriceValueCastDecisionEXTBO extbo = valueProducts.getValue();

            PriceValueOrg org = new PriceValueOrg();
            BeanUtils.copyProperties(extbo, org);
            String strCode = extbo.getGroupId()+"&"+extbo.getBatchCode()+"&"+extbo.getProductCode()+"&"+extbo.getFreeTypeName()+"&"+extbo.getBusinessTypeName()+"&"+extbo.getProTypeName();

            String pkId = timePkIdMap.get(strCode);

            org.setOpenTime(openTimeMap.get(pkId));
            org.setOpenTimeActual(openTimeActualMap.get(pkId));
            org.setSupplyTime(supplyTimeMap.get(pkId));
            org.setSupplyTimeActual(supplyTimeActualMap.get(pkId));
            org.setAdvanceSaleTime(advanceSaleTimeMap.get(pkId));
            org.setAdvanceSaleTimeActual(advanceSaleTimeActualMap.get(pkId));
            org.setOpenSaleTime(openSaleTimeMap.get(pkId));
            org.setOpenSaleTimeActual(openSaleTimeActualMap.get(pkId));
            org.setCappingTime(cappingTimeMap.get(pkId));
            org.setCappingTimeActual(cappingTimeActualMap.get(pkId));
            org.setCompletedTime(completedTimeMap.get(pkId));
            org.setCompletedTimeActual(completedTimeActualMap.get(pkId));
            org.setCarryOverTime(carryOverTimeMap.get(pkId));
            org.setCarryOverTimeActual(carryOverTimeActualMap.get(pkId));
            org.setActualDeliveryTime(actualDeliveryTimeMap.get(pkId));
            org.setActualDeliveryTimeActual(actualDeliveryTimeActualMap.get(pkId));
            org.setContractDeliveryTime(contractDeliveryTimeMap.get(pkId));
            org.setContractDeliveryTimeActual(contractDeliveryTimeActualMap.get(pkId));
            org.setUpdateTime(now);

            updateTimeOrgList.add(org);
        }

        //更新时间
        if(CollectionUtils.isNotEmpty(updateTimeOrgList)){
            priceValueOrgMapper.updateBatch(updateTimeOrgList);
        }

        //如果审批通过通知供货计划
        if (versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey()) || versionState.equals(VersionStatusEnum.SYSGENERATION.getKey())){
            try{
                supplyPlanVersionService.createSupplyPlanVersion(priceVersionId, versionType, Constants.SYS);
            }catch (Exception e){
                logger.error("################  panoCastDecisionVersionChange  supplyPlanVersionService: "+e);
            }
        }

        priceRefreshVersionLogInfo(priceVersion, instId, now, "货值上游变动刷新版本:楼栋计划时间节点变更", "#############     investmentRefreshTimeNode    saveVersionLogInfo   error:");
    }

    /**
     * 投资版代办信息
     */
    private void noticeInvestmentCreateAndHandle(String projectFid, MdmStage mdmStage, MdmProject mdmProject, PanoPlanCastDecisionBO panoPlanCastDecisionBO, String processingMode, String processingState) {
        LocalDateTime now = LocalDateTime.now();

        //查询代办信息
        List<SysNotice> notices = sysNoticeService.selectModeByProjectFidAndVersionType(projectFid, ModuleTypeEunm.PRICE.getKey(), VersionTypeEunm.INVESTMENT.getKey(), ProcessingStateEnum.UNTREATED.getKey(),IsDeleteEnum.NO.getKey());

        //系统将该项目分期之前同类待办设置为无效待办，同时删除新门户该分期之前同类待办
        sysNoticeService.updateNoticeStateByStageIdAndType(projectFid, ModuleTypeEunm.PRICE.getKey(), VersionTypeEunm.INVESTMENT.getKey(), ProcessingStateEnum.FAILURE.getKey(), Constants.SYS, now , IsDeleteEnum.NO.getKey());

        if(CollectionUtils.isNotEmpty(notices)){

            for(SysNotice notice : notices){
                String instanceId = notice.getPortalInstanceId();

                if(StringUtils.isNotEmpty(instanceId)){
                    //删除门户代办消息
                    IdmUser idmUser = new IdmUser();
                    idmUser.setAlias(Constants.SYS);
                    idmUser.setUsercn(Constants.SYS_NAME);
                    commonService.updatePortalProcess(instanceId, OperatorTypeEnum.TRANSFERRED_TO_OFFICE.getKey(), idmUser, null);
                }
            }
        }

        //发送待办提醒,填报战规版货值
        SysNotice notice = new SysNotice();
        notice.setId(UUIDUtils.create());
        StringBuffer taskRemark = new StringBuffer();
        taskRemark.append("[填报投资版货值]").append(mdmProject.getProjectName()).append("项目").append(mdmStage.getStageName())
                .append("分期有了新版投资版").append("楼栋计划：").append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType())
                .append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion()).append("-")
                .append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate().toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd")))
                .append("，请填报该分期投资版货值。");

        notice.setTaskName(Constants.NOTICE_PANO);
        notice.setTaskType(ModuleTypeEunm.PRICE.getKey());
        notice.setTaskSource(VersionTypeEunm.INVESTMENT.getKey());
        notice.setProcessingMode(processingMode);
        notice.setReceivingVersionId(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
        notice.setReceivingVersionNo(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());
        notice.setProjectId(mdmStage.getProjectId());
        notice.setStagesId(mdmStage.getProjectFid());
        notice.setAffectedVersionStage(NoticeAffectedEnum.PANO_CHANGE.getKey());
        notice.setState(processingState);
        notice.setDescInfo(taskRemark.toString());
        notice.setIsDelete(IsDeleteEnum.NO.getKey());
        notice.setCreateBy(Constants.SYS);
        notice.setCreateTime(now);

        //发送门户代办提醒
        String instanceId = sendBackLog(mdmStage.getProjectId(), mdmStage.getProjectFid(), taskRemark.toString(), null);

        notice.setPortalInstanceId(instanceId);
        sysNoticeService.save(notice);
    }

    /**
     * 楼栋计划/楼栋业态面积 战规后货值版本变更
     * @param projectFid 分期id
     * @param sourceVersionType 数据来源类型
     * @param source 数据来源
     * @param instId esb报文instId
     * @return List<PriceValueCompareVO> 货值版本变动信息
     */
    @Override
    public List<PriceValueCompareVO> panoDynamicVersionChange(String projectFid, String sourceVersionType, String source, String instId) {
        LocalDateTime now = LocalDateTime.now();

        //查询指定分期信息
        MdmStage mdmStage = stageService.selectById(projectFid);
        if(mdmStage == null){
            throw new MsgException(CodeEnum.STAGE_NON_EXISTENT);
        }

        //查询指定项目信息
        MdmProject mdmProject = projectService.selectByProjectId(mdmStage.getProjectId(), IsDeleteEnum.NO.getKey());
        if(mdmProject == null){
            throw new MsgException(CodeEnum.SYS_PROJECT_ERROR);
        }

        //获取最新的动态版楼栋计划
        PanoPlanCastDecisionBO panoPlanCastDecisionBO = panoplanBuildPlanService.selectNewestWarPlanByFid(projectFid, VersionTypeEunm.DYNAMIC.getKey(), IsDeleteEnum.NO.getKey());

        //获取最新的动态版楼栋面积
        MdmBuildAreaBO mdmProductWarPlanBO = buildAreaService.selectNewestByFid(projectFid, VersionTypeEunm.DYNAMIC.getKey(), IsDeleteEnum.NO.getKey());
        if(mdmProductWarPlanBO == null){
            throw new MsgException(CodeEnum.NON_GROUPBLD_AREA);
        }

        //全景计划系统最新版楼栋计划项目树与主数据系统最新版面积版本项目树不匹配，不允许创建新版本；
        mdmToPanoGroupVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO);

        mdmToPanoProductVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO);

        Map<String, String> panoplanBuildPlanItemMap = new HashMap<>();
        Map<String, PanoplanBuildPlanItem> panoplanItemMap = new HashMap<>();
        Map<String, String> panoplanItemIdMap = new HashMap<>();
        if(panoPlanCastDecisionBO.getBuildItems().size() == mdmProductWarPlanBO.getBuildItems().size()){
            List<String> buildList = new ArrayList<String>();
            for(PanoplanBuildPlanItem buildItem : panoPlanCastDecisionBO.getBuildItems()){
                buildList.add(buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId());
                panoplanBuildPlanItemMap.put(buildItem.getId(), buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId());
                panoplanItemMap.put(buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId(), buildItem);
                panoplanItemIdMap.put(buildItem.getId(), buildItem.getBldPrdId());
            }

            for(MdmBuildAreaDetailBO buildAreaBO : mdmProductWarPlanBO.getBuildItems()){
                if(buildList.contains(buildAreaBO.getGroupId()+"&"+buildAreaBO.getProductCode()+"&"+buildAreaBO.getBldPrdId())){
                    String businessType = buildAreaBO.getBusinessType();
                    if (businessType.equals(SalyTypeEnum.SALABLE.getKey()) ||
                            businessType.equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey()) ){
                        BigDecimal totalSaleArea = buildAreaBO.getTotalSaleArea()==null?new BigDecimal(0):buildAreaBO.getTotalSaleArea();
                        if(!isParkList.contains(buildAreaBO.getProductCode())){
                            if (totalSaleArea.compareTo(new BigDecimal(0)) <= 0){
                                CodeEnum.NON_PANOPLAN_BUILD.setMessage("楼栋信息不完整:"+buildAreaBO.getFormatBuildingName()+"面积小于等于0");
                                throw new MsgException(CodeEnum.NON_PANOPLAN_BUILD);
                            }
                        }

                        Integer roomNum = buildAreaBO.getRoomNum()==null?0:buildAreaBO.getRoomNum();
                        if (roomNum <= 0){
                            if (!isParkList.contains(buildAreaBO.getProductCode())){
                                CodeEnum.NON_PANOPLAN_BUILD.setMessage("楼栋信息不完整:"+buildAreaBO.getFormatBuildingName()+"套数/个数小于等于0");
                                throw new MsgException(CodeEnum.NON_PANOPLAN_BUILD);
                            }
                        }
                    }

                    buildList.remove(buildAreaBO.getGroupId()+"&"+buildAreaBO.getProductCode()+"&"+buildAreaBO.getBldPrdId());
                }else{
                    throw new MsgException(CodeEnum.NON_MATCH_VERSIONS);
                }
            }

            if(CollectionUtils.isNotEmpty(buildList)){
                throw new MsgException(CodeEnum.NON_MATCH_VERSIONS);
            }
        }else{
            throw new MsgException(CodeEnum.NON_ORG_VERSIONS);
        }

        ///将节点为取预售证时间的存储在指定Map中
        Map<String, LocalDateTime> openTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeVirtualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        List<PanoplanBuildPlanItemDetail> details = panoPlanCastDecisionBO.getDetails();
        if(CollectionUtils.isNotEmpty(details)){
            for (int i = 0;i < details.size(); i++){
                PanoplanBuildPlanItemDetail panoplanBuildPlanItemDetail = details.get(i);
                String nodeCode = panoplanBuildPlanItemDetail.getNodeCode();
                String pkId = panoplanBuildPlanItemDetail.getPkId();
                String code = panoplanItemIdMap.get(pkId);

                if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00002.getKey())){
                    openTimeMap.put(code, panoplanBuildPlanItemDetail.getPlannedFinishDate());
                    openTimeActualMap.put(code, panoplanBuildPlanItemDetail.getActualFinishDate());
                }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00001.getKey())){
                    advanceSaleTimeMap.put(code, panoplanBuildPlanItemDetail.getPlannedFinishDate());
                    advanceSaleTimeActualMap.put(code, panoplanBuildPlanItemDetail.getActualFinishDate());
                }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00002.getKey())){
                    supplyTimeMap.put(code, panoplanBuildPlanItemDetail.getPlannedFinishDate());
                    supplyTimeActualMap.put(code, panoplanBuildPlanItemDetail.getActualFinishDate());
                    supplyTimeVirtualMap.put(code, panoplanBuildPlanItemDetail.getVirtualFinishDate());
                }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00003.getKey())){
                    openSaleTimeMap.put(code, panoplanBuildPlanItemDetail.getPlannedFinishDate());
                    openSaleTimeActualMap.put(code, panoplanBuildPlanItemDetail.getActualFinishDate());
                }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00003.getKey())){
                    cappingTimeMap.put(code, panoplanBuildPlanItemDetail.getPlannedFinishDate());
                    cappingTimeActualMap.put(code, panoplanBuildPlanItemDetail.getActualFinishDate());
                }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00004.getKey())){
                    completedTimeMap.put(code, panoplanBuildPlanItemDetail.getPlannedFinishDate());
                    completedTimeActualMap.put(code, panoplanBuildPlanItemDetail.getActualFinishDate());
                }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00006.getKey())){
                    carryOverTimeMap.put(code, panoplanBuildPlanItemDetail.getPlannedFinishDate());
                    carryOverTimeActualMap.put(code, panoplanBuildPlanItemDetail.getActualFinishDate());
                }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00005.getKey())){
                    actualDeliveryTimeMap.put(code, panoplanBuildPlanItemDetail.getPlannedFinishDate());
                    actualDeliveryTimeActualMap.put(code, panoplanBuildPlanItemDetail.getActualFinishDate());
                }else if(StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.NODE_000.getKey())){
                    contractDeliveryTimeMap.put(code, panoplanBuildPlanItemDetail.getPlannedFinishDate());
                    contractDeliveryTimeActualMap.put(code, panoplanBuildPlanItemDetail.getActualFinishDate());
                }
            }
        }

        //分期有可售或阶段性自持产品构成没有批次或供货日期时，不允许新建该分期价格版本
        List<PanoplanBuildPlanItem> panoProductItems = panoPlanCastDecisionBO.getBuildItems();
        for (int i = 0;i < panoProductItems.size(); i++){
            PanoplanBuildPlanItem panoplanBuildPlanItem = panoProductItems.get(i);
            String saleNum = panoplanBuildPlanItem.getSaleNum();
            if(StringUtils.isNotEmpty(saleNum) && (saleNum.equals(SalyTypeEnum.SALABLE.getKey())
                    || saleNum.equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey()))){
                LocalDateTime supplyTime = supplyTimeMap.get(panoplanBuildPlanItem.getBldPrdId());
                LocalDateTime supplyActualTime = supplyTimeActualMap.get(panoplanBuildPlanItem.getBldPrdId());
                LocalDateTime supplyVirtualTime = supplyTimeVirtualMap.get(panoplanBuildPlanItem.getBldPrdId());
                if(supplyTime == null && supplyActualTime == null && supplyVirtualTime == null){
                    throw new MsgException(CodeEnum.NON_PANO_TIME);
                }
            }
        }

        PriceVersion newestDynamicPriceVersion = priceVersionService.getNewestPriceVersionAllVersionState(projectFid);

        //去除投资版
        if(newestDynamicPriceVersion != null){
            if(newestDynamicPriceVersion.getVersionType().equals(VersionTypeEunm.INVESTMENT.getKey())){
                newestDynamicPriceVersion = null;
            }
        }

        //是否存在战规后货值版本
        if (newestDynamicPriceVersion != null){
            //查询最新分期楼栋信息
            Map<String, PriceValueCastDecisionAllOrgEXTBO> extValueBuildMap = new HashMap<String, PriceValueCastDecisionAllOrgEXTBO>();
            List<PriceValueCastDecisionAllOrgEXTBO> newestBuildList = priceValueOrgMapper.selectWPProductOrgAndByBuildOrgVersionId(newestDynamicPriceVersion.getId(), IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isNotEmpty(newestBuildList)){
                for (PriceValueCastDecisionAllOrgEXTBO extBuild : newestBuildList) {
                    extValueBuildMap.put(extBuild.getCode()+"&"+extBuild.getOrgId(), extBuild);
                }
            }

            //是否有差异List
            List<PriceValueCompareVO> isDifferenceList = new ArrayList<PriceValueCompareVO>();

            //比较主数据楼栋信息和货值楼栋信息是否一致
            List<PriceValueCompareVO> buildCompareVOList = new ArrayList<PriceValueCompareVO>();
            wc : for (MdmBuildAreaDetailBO mdmBuildItem : mdmProductWarPlanBO.getBuildItems()){
                String code = mdmBuildItem.getProductCode()+"&"+mdmBuildItem.getBldPrdId();

                boolean isDifference = false;
                boolean isparking = isParkList.contains(mdmBuildItem.getProductCode());

                PriceValueCastDecisionAllOrgEXTBO valueBuildItem = extValueBuildMap.get(code);
                if (valueBuildItem != null){

                    //如果楼栋都是不可租售和可租的则不对比
                    String mdmBusinessType = mdmBuildItem.getBusinessType();
                    String valueBusinessType = valueBuildItem.getBusinessType();
                    if ((mdmBusinessType.equals(SalyTypeEnum.RENTED.getKey()) || mdmBusinessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()))
                        && (valueBusinessType.equals(SalyTypeEnum.RENTED.getKey()) || valueBusinessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()))) {
                        extValueBuildMap.remove(code);
                        continue wc;
                    }

                    //全部归集的楼栋不对比面积、套数、经营方式、属性标签、装修标准
                    Integer isTotalCollect = valueBuildItem.getIsTotalCollect();
                    if(isTotalCollect == null || isTotalCollect.equals(IsDeleteEnum.NO.getKey())){
                        //判断楼栋是否全部已供
                        if (isparking){
                            //已售车位数+已定价未售车位数+自持车位数+未推售车位数 ≥ 主数据车位数，即为全部定价
                            Integer parkingSold = valueBuildItem.getParkingSold()==null?0:valueBuildItem.getParkingSold();
                            Integer parkingPriced = valueBuildItem.getParkingPriced()==null?0:valueBuildItem.getParkingPriced();
                            Integer parkingZc = valueBuildItem.getParkingZc()==null?0:valueBuildItem.getParkingZc();
                            Integer forsaleParkingNum = valueBuildItem.getForsaleParkingNum()==null?0:valueBuildItem.getForsaleParkingNum();
                            Integer totalCollectNum = parkingSold + parkingPriced + parkingZc + forsaleParkingNum;

                            Integer mdmRoomNum = mdmBuildItem.getRoomNum()==null?0:mdmBuildItem.getRoomNum();
                            if (totalCollectNum >= mdmRoomNum){
                                extValueBuildMap.remove(code);
                                continue wc;
                            }
                        }else {
                            //已售房源数+已定价未售房源数+自持房源数 ≥ 主数据房源数
                            // 或 已售房源面积+已定价未售房源面积+自持房源面积 ≥ 主数据房源面积  即为全部定价
                            Integer roomSold = valueBuildItem.getRoomSold()==null?0:valueBuildItem.getRoomSold();
                            Integer roomPriced = valueBuildItem.getRoomPriced()==null?0:valueBuildItem.getRoomPriced();
                            Integer roomZc = valueBuildItem.getRoomZc()==null?0:valueBuildItem.getRoomZc();
                            Integer totalCollectNum = roomSold + roomPriced + roomZc;

                            Integer mdmRoomNum = mdmBuildItem.getRoomNum()==null?0:mdmBuildItem.getRoomNum();
                            if (totalCollectNum >= mdmRoomNum){
                                extValueBuildMap.remove(code);
                                continue wc;
                            }

                            BigDecimal areaSold = valueBuildItem.getAreaSold();
                            BigDecimal areaPriced = valueBuildItem.getAreaPriced();
                            BigDecimal areaZc = valueBuildItem.getAreaZc();
                            BigDecimal totalCollectArea = BigDecimalADD(BigDecimalADD(areaSold, areaPriced), areaZc);

                            BigDecimal mdmRoomArea = mdmBuildItem.getTotalSaleArea()==null?new BigDecimal(0):mdmBuildItem.getTotalSaleArea();
                            if (totalCollectArea.compareTo(mdmRoomArea) >= 0){
                                extValueBuildMap.remove(code);
                                continue wc;
                            }
                        }

                        PriceValueCompareVO buildCompareVO = new PriceValueCompareVO();
                        buildCompareVO.setId(UUIDUtils.create());
                        buildCompareVO.setType(OrgTypeEunm.ORG_BUILD.getKey());
                        buildCompareVO.setName(mdmBuildItem.getFormatBuildingName());
                        buildCompareVO.setCode(mdmBuildItem.getGroupId()+"&"+mdmBuildItem.getProductCode());

                        //是否车位楼栋
                        if (isparking){
                            buildCompareVO.setIsParking(IsDeleteEnum.YES.getKey());
                        }else {
                            buildCompareVO.setIsParking(IsDeleteEnum.NO.getKey());
                        }

                        //货值和主数据信息进行比较
                        Integer mdmRoomNum = mdmBuildItem.getRoomNum()==null?0:mdmBuildItem.getRoomNum();
                        Integer num = valueBuildItem.getNum()==null?0:valueBuildItem.getNum();
                        if (!mdmRoomNum.equals(num)){
                            List<PriceValueCompareVO.PriceValueCompareDetailVO> detailVOList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                            PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                            detailVO.setChangeType(Constants.NUM_CHANGE);
                            Integer subNum = mdmRoomNum - valueBuildItem.getNum();
                            if (subNum > 0) {
                                detailVO.setChangeType(Constants.ADD_NUM_CHANGE + Math.abs(subNum));
                                detailVO.setChangeDetail(valueBuildItem.getNum()+"变为"+mdmRoomNum);
                            } else {
                                detailVO.setChangeType(Constants.REDUCE_NUM_CHANGE + Math.abs(subNum));
                                detailVO.setChangeDetail(valueBuildItem.getNum()+"变为"+mdmRoomNum);
                            }

                            detailVOList.add(detailVO);
                            buildCompareVO.setDetailList(detailVOList);
                        }

                        if (!isparking){
                            BigDecimal mdmRoomArea = mdmBuildItem.getTotalSaleArea()==null?new BigDecimal(0):mdmBuildItem.getTotalSaleArea();
                            BigDecimal saleArea = valueBuildItem.getSaleArea()==null?new BigDecimal(0):valueBuildItem.getSaleArea();
                            if (!mdmRoomArea.equals(saleArea)){
                                List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                                if (CollectionUtils.isEmpty(detailList)){
                                    detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                                }
                                PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                                detailVO.setChangeType(Constants.AREA_CHANGE);
                                BigDecimal subArea = mdmRoomArea.subtract(valueBuildItem.getSaleArea()).setScale(4, BigDecimal.ROUND_HALF_UP);
                                if (subArea.compareTo(new BigDecimal(0)) > 0) {
                                    detailVO.setChangeType(Constants.ADD_AREA_CHANGE + subArea.abs());
                                    detailVO.setChangeDetail(valueBuildItem.getSaleArea()+"变为"+mdmRoomArea);
                                } else {
                                    detailVO.setChangeType(Constants.REDUCE_AREA_CHANGE + subArea.abs());
                                    detailVO.setChangeDetail(valueBuildItem.getSaleArea()+"变为"+mdmRoomArea);
                                }

                                detailList.add(detailVO);
                                buildCompareVO.setDetailList(detailList);
                            }
                        }

                        if (!mdmBuildItem.getFreeType().equals(valueBuildItem.getFreeType())){
                            List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                            if (CollectionUtils.isEmpty(detailList)){
                                detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                            }
                            PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                            detailVO.setChangeType(Constants.FREE_TYPE_CHANGE);
                            detailVO.setChangeDetail(valueBuildItem.getFreeTypeName()+"变为"+mdmBuildItem.getFreeTypeName());

                            detailList.add(detailVO);
                            buildCompareVO.setDetailList(detailList);
                            isDifference = true;
                        }

                        if (!mdmBuildItem.getBusinessType().equals(valueBuildItem.getBusinessType())){
                            List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                            if (CollectionUtils.isEmpty(detailList)){
                                detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                            }
                            PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                            detailVO.setChangeType(Constants.BUSINESS_TYPE_CHANGE);
                            detailVO.setChangeDetail(valueBuildItem.getBusinessTypeName()+"变为"+mdmBuildItem.getBusinessTypeName());

                            detailList.add(detailVO);
                            buildCompareVO.setDetailList(detailList);
                            isDifference = true;
                        }

                        if (!mdmBuildItem.getProType().equals(valueBuildItem.getProType())){
                            List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                            if (CollectionUtils.isEmpty(detailList)){
                                detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                            }
                            PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                            detailVO.setChangeType(Constants.PRO_TYPE_CHANGE);
                            detailVO.setChangeDetail(valueBuildItem.getProTypeName()+"变为"+mdmBuildItem.getProTypeName());

                            detailList.add(detailVO);
                            buildCompareVO.setDetailList(detailList);
                            isDifference = true;
                        }

                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                        if(CollectionUtils.isNotEmpty(detailList)){

                            buildCompareVO.setChangeBeforeNum(valueBuildItem.getNum());
                            buildCompareVO.setChangeBeforeArea(valueBuildItem.getSaleArea());

                            buildCompareVO.setChangeAfterNum(mdmBuildItem.getRoomNum());
                            buildCompareVO.setChangeAfterArea(mdmBuildItem.getTotalSaleArea());

                            buildCompareVOList.add(buildCompareVO);
                        }

                        if (isDifference){
                            isDifferenceList.add(buildCompareVO);
                        }
                    }
                }else{
                    //不对比 不可租售 和 可租
                    if (mdmBuildItem.getBusinessType().equals(SalyTypeEnum.SALABLE.getKey()) || mdmBuildItem.getBusinessType().equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey())) {
                        PriceValueCompareVO buildCompareVO = new PriceValueCompareVO();
                        buildCompareVO.setId(UUIDUtils.create());
                        buildCompareVO.setType(OrgTypeEunm.ORG_BUILD.getKey());
                        buildCompareVO.setName(mdmBuildItem.getFormatBuildingName());
                        buildCompareVO.setCode(mdmBuildItem.getGroupId()+"&"+mdmBuildItem.getProductCode());

                        //是否车位楼栋
                        if (isparking){
                            buildCompareVO.setIsParking(IsDeleteEnum.YES.getKey());
                        }else {
                            buildCompareVO.setIsParking(IsDeleteEnum.NO.getKey());
                        }

                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                        if (CollectionUtils.isEmpty(detailList)){
                            detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        }
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();

                        detailVO.setChangeType(Constants.UPDATE_BUILD_TYPE);
                        detailVO.setChangeDetail(Constants.UPDATE_BUILD_DETAIL + "增加了楼栋"+mdmBuildItem.getFormatBuildingName());

                        detailList.add(detailVO);
                        buildCompareVO.setDetailList(detailList);

                        isDifferenceList.add(buildCompareVO);
                        buildCompareVOList.add(buildCompareVO);
                    }
                }

                extValueBuildMap.remove(code);
            }

            if (CollectionUtils.isNotEmpty(extValueBuildMap)){
                for (Map.Entry<String, PriceValueCastDecisionAllOrgEXTBO> extboMap : extValueBuildMap.entrySet()){
                    PriceValueCastDecisionAllOrgEXTBO value = extboMap.getValue();
                    //不对比 不可租售 和 可租
                    if (!value.getBusinessType().equals(SalyTypeEnum.RENTED.getKey()) && !value.getBusinessType().equals(SalyTypeEnum.NOT_RENTABLE.getKey())){
                        PriceValueCompareVO buildCompareVO = new PriceValueCompareVO();
                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                        if (CollectionUtils.isEmpty(detailList)){
                            detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        }
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();

                        detailVO.setChangeType(Constants.UPDATE_BUILD_TYPE);
                        detailVO.setChangeDetail(Constants.UPDATE_BUILD_DETAIL + "删除了楼栋"+value.getOrgName());

                        detailList.add(detailVO);
                        buildCompareVO.setDetailList(detailList);

                        isDifferenceList.add(buildCompareVO);
                        buildCompareVOList.add(buildCompareVO);
                    }
                }
            }

            //判断货值状态 和 类型
            String newestversionId = newestDynamicPriceVersion.getId();
            String versionState = newestDynamicPriceVersion.getVersionState();
            String versionType = newestDynamicPriceVersion.getVersionType();

            IdmUser sysUser = new IdmUser();
            sysUser.setAlias(Constants.SYS);
            sysUser.setUsercn(Constants.SYS_NAME);

            //查看差异是需要手动处理
            if(CollectionUtils.isNotEmpty(isDifferenceList)){ //需要手动处理
                if (versionState.equals(VersionStatusEnum.APPROVED.getKey())
                        || versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())
                        || versionState.equals(VersionStatusEnum.SYSGENERATION.getKey())){
                    //生成代办并将之前的代办置为无效
                    noticeCreateAndHandle(projectFid, source, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.MANUAL.getKey());
                }else{
                    //如果项目在锁定状态中，不能刷新货值版本
                    boolean lockByProjectId = projectLockRecordService.isLockByProjectId(mdmStage.getProjectId());
                    if(!lockByProjectId){
                        //将变动直接刷新到该分期最新战规后货值版本中
                        if(versionType.equals(VersionTypeEunm.DYNAMIC.getKey())){
                            priceValueRefreshInfo(projectFid, newestDynamicPriceVersion, panoPlanCastDecisionBO, mdmProductWarPlanBO, instId, source, isDifferenceList);

                            noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_REFRESH:Constants.NOTICE_MDM_REFRESH, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, newestDynamicPriceVersion.getId(), newestDynamicPriceVersion.getVersionType(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());
                        }else if(versionType.equals(VersionTypeEunm.GETPRICE.getKey()) || versionType.equals(VersionTypeEunm.WARPLAN.getKey())){
                            //生成代办并将之前的代办置为无效
                            noticeCreateAndHandle(projectFid, source, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.MANUAL.getKey());
                        }
                    }else{
                        //生成代办并将之前的代办置为无效
                        noticeCreateAndHandle(projectFid, source, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.MANUAL.getKey());
                    }
                }
            }else{  //自动处理
                //如果项目在锁定状态中，不能刷新货值版本
                boolean lockByProjectId = projectLockRecordService.isLockByProjectId(mdmStage.getProjectId());
                if(!lockByProjectId) {
                    versionCreateOrRefreshJudgeInfo(projectFid, sourceVersionType, source, instId, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, panoplanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, newestDynamicPriceVersion, isDifferenceList, buildCompareVOList, newestversionId, versionState, versionType, sysUser);
                } else{
                    //楼栋计划锁定刷新时间节点
                    if (StringUtils.isNotEmpty(source) && source.equals(Constants.PANO)){
                        versionCreateOrRefreshJudgeInfo(projectFid, sourceVersionType, source, instId, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, panoplanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, newestDynamicPriceVersion, isDifferenceList, buildCompareVOList, newestversionId, versionState, versionType, sysUser);
                    }else{
                        noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_DELAY:Constants.NOTICE_MDM_DELAY, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, newestDynamicPriceVersion.getId(), newestDynamicPriceVersion.getVersionType(), ProcessingModeEnum.SYSTEM_DELAY.getKey(), ProcessingStateEnum.UNTREATED.getKey(), VersionTypeEunm.DYNAMIC.getKey());
                    }
                }
            }
        }else{
            //接收到推送的楼栋计划/面积版本是否是战规版
            if(sourceVersionType.equals(VersionTypeEunm.WARPLAN.getKey())){
                noticeCreateAndHandle(projectFid, source, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, VersionTypeEunm.WARPLAN.getKey(), ProcessingModeEnum.MANUAL.getKey());
            }else{
                noticeCreateAndHandle(projectFid, source, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.MANUAL.getKey());
            }
        }

        logger.info("###########################    panoDynamicVersionChange end:"+LocalDateTime.now());
        return null;
    }

    protected void versionCreateOrRefreshJudgeInfo(String projectFid, String sourceVersionType, String source, String instId, LocalDateTime now, MdmStage mdmStage, MdmProject mdmProject, PanoPlanCastDecisionBO panoPlanCastDecisionBO, MdmBuildAreaBO mdmProductWarPlanBO, Map<String, PanoplanBuildPlanItem> panoplanItemMap, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, PriceVersion newestDynamicPriceVersion, List<PriceValueCompareVO> isDifferenceList, List<PriceValueCompareVO> buildCompareVOList, String newestversionId, String versionState, String versionType, IdmUser sysUser) {
        if(versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())){
            //自动生成该分期 新版动态版货值 （当前年月）
            String versionId = createSysDynamicVersion(projectFid, VersionTypeEunm.DYNAMIC.getKey(), VersionCreateEnum.AUTOMATICCREATE.getKey(), sysUser, source.equals("pano")?2:1, instId , IsDeleteEnum.YES.getKey(), null);

            noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_CREATE:Constants.NOTICE_MDM_CREATE, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, versionId, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());

            supplyPlanVersionService.createSupplyPlanVersion(versionId, VersionTypeEunm.DYNAMIC.getKey(), Constants.SYS);
        }else if (versionState.equals(VersionStatusEnum.SYSGENERATION.getKey())){
            //查看时间归属的月份
            LocalDate ascriptionDate = LocalDate.now();
            if(versionType.equals(VersionTypeEunm.DYNAMIC.getKey())){

                int day = now.getDayOfMonth();
                int hour = now.getHour();
                if (day == Constants.ONE && hour <=  Constants.SIX){//一号
                    ascriptionDate = ascriptionDate.minusMonths(1);
                }
            }

            //查看当前年月是否已有动态版货值
            PriceVersion monthToPriceVersion = priceVersionService.selectNewestDynamicToMonthByPrice(projectFid, VersionTypeEunm.DYNAMIC.getKey(), ascriptionDate, IsDeleteEnum.NO.getKey());
            if (monthToPriceVersion != null){
                //版本刷新或生成验证
                versionCreateOrRefreshVerification(projectFid, source, instId, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, panoplanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, newestDynamicPriceVersion, buildCompareVOList, newestversionId, versionType);
            }else{
                //没有，自动生成该分期新版动态版货值(当前年月)
                String versionId = createSysDynamicVersion(projectFid, VersionTypeEunm.DYNAMIC.getKey(), VersionCreateEnum.AUTOMATICCREATE.getKey(), sysUser, source.equals("pano")?2:1, instId, null, null);

                noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_CREATE:Constants.NOTICE_MDM_CREATE, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, versionId, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());

                supplyPlanVersionService.createSupplyPlanVersion(versionId, VersionTypeEunm.DYNAMIC.getKey(), Constants.SYS);
            }
        }else if(versionState.equals(VersionStatusEnum.APPROVED.getKey())){
            //审批中状态只处理时间节点变化
            if(CollectionUtils.isNotEmpty(buildCompareVOList)){
                //生成代办并将之间的代办置为无效
                noticeCreateAndHandle(projectFid, source, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, newestDynamicPriceVersion.getVersionType(), ProcessingModeEnum.MANUAL.getKey());
            }else{
                if (source != null && source.equals(Constants.PANO)){
                    panoTimeItemDetailChangeInfo(now, panoPlanCastDecisionBO, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, newestDynamicPriceVersion);

                    noticeRecordProcessedInfo(Constants.NOTICE_PANO_TIME_ITEM, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, newestDynamicPriceVersion.getId(), newestDynamicPriceVersion.getVersionType(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());
                }else if(source != null && source.equals(Constants.MDM)){
                    noticeRecordProcessedInfo(Constants.NOTICE_MDM_DELAY, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, newestDynamicPriceVersion.getId(), newestDynamicPriceVersion.getVersionType(), ProcessingModeEnum.SYSTEM_DELAY.getKey(), ProcessingStateEnum.UNTREATED.getKey(), versionType);
                }
            }
        }else if (versionState.equals(VersionStatusEnum.NOTPREPARED.getKey()) ||
                versionState.equals(VersionStatusEnum.ORGANIZATION.getKey()) ||
                versionState.equals(VersionStatusEnum.EXAMINEDAPPROVED.getKey()) ||
                versionState.equals(VersionStatusEnum.FAILUREAPPROVED.getKey())){
            //判断当前要刷新的版本是否为战规版
            if(versionType.equals(VersionTypeEunm.WARPLAN.getKey())){
                if (sourceVersionType.equals(VersionTypeEunm.WARPLAN.getKey())){
                    //货值刷新
                    priceValueRefreshInfo(projectFid, newestDynamicPriceVersion, panoPlanCastDecisionBO, mdmProductWarPlanBO, instId, source, isDifferenceList);

                    noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_REFRESH:Constants.NOTICE_MDM_REFRESH, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, newestDynamicPriceVersion.getId(), newestDynamicPriceVersion.getVersionType(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());
                }else{

                    //生成代办并将之间的代办置为无效
                    noticeCreateAndHandle(projectFid, source, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.MANUAL.getKey());
                }
            }else if (versionType.equals(VersionTypeEunm.GETPRICE.getKey())){

                //生成代办并将之间的代办置为无效
                noticeCreateAndHandle(projectFid, source, now, mdmStage, mdmProject, panoPlanCastDecisionBO, mdmProductWarPlanBO, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.MANUAL.getKey());

            }else if (versionType.equals(VersionTypeEunm.DYNAMIC.getKey())){
                //货值刷新
                priceValueRefreshInfo(projectFid, newestDynamicPriceVersion, panoPlanCastDecisionBO, mdmProductWarPlanBO, instId, source, isDifferenceList);

                noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_REFRESH:Constants.NOTICE_MDM_REFRESH, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, newestDynamicPriceVersion.getId(), newestDynamicPriceVersion.getVersionType(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());
            }
        }
    }

    public void priceValueRefreshInfo(String projectFid, PriceVersion oldPriceVersion, PanoPlanCastDecisionBO panoPlanCastDecisionBO, MdmBuildAreaBO mdmProductWarPlanBO, String instId, String source, List<PriceValueCompareVO> isDifferenceList) {
        logger.info("###########################    priceValueRefresh start:"+LocalDateTime.now());

        LocalDateTime now = LocalDateTime.now();

        //查询指定分期信息
        MdmStage mdmStage = stageService.selectById(projectFid);
        if(mdmStage == null){
            throw new MsgException(CodeEnum.STAGE_NON_EXISTENT);
        }

        Map<String, String> panoplanBuildPlanItemMap = new HashMap<>();
        Map<String, PanoplanBuildPlanItem> panoplanItemMap = new HashMap<>();
        mdmToPanoBuildVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO, panoplanBuildPlanItemMap, panoplanItemMap);

        //楼栋计划匹配节点
        Map<String, LocalDateTime> openTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeVirtualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        panoTimeItemNodeMapInfo(panoPlanCastDecisionBO, panoplanBuildPlanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap);

        //查询取数系统
        String fetchSysCode = oldPriceVersion.getCountingSystemCode();

        Map<String, PriceValueOrg> presaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已售车位
        Map<String, PriceValueOrg> prenotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已定价未售车位
        Map<String, PriceValueOrg> preSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版可售车位
        Map<String, PriceValueOrg> preNotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版未推售车位
        Map<String, List<PriceValueOrg>> preHouseMap = new HashMap<String, List<PriceValueOrg>>(); //上一版房源包
        Map<String, PriceValueOrg> preBuildMap = new HashMap<String, PriceValueOrg>(); //上一版楼栋
        Map<String, BigDecimal> preBuildAvPriceMap = new HashMap<String, BigDecimal>();//上一版楼栋均价
        List<PriceValueCastDecisionAllOrgEXTBO> priceValueCastDecisionAllOrgEXTBOS = priceValueOrgMapper.selectHouseAndPark(oldPriceVersion.getId(), IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(priceValueCastDecisionAllOrgEXTBOS)){
            priceRefreshPreOrgInfo(presaleParkMap, prenotSaleParkMap, preSaleParkMap, preNotSaleParkMap, preHouseMap, priceValueCastDecisionAllOrgEXTBOS);
        }

        List<PriceValueOrg> oldBuildList = priceValueOrgService.selectBuildByVersionId(oldPriceVersion.getId(), OrgTypeEunm.ORG_BUILD.getKey(), null, IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(oldBuildList)){
            for (PriceValueOrg oldBuild : oldBuildList){
                preBuildMap.put(oldBuild.getOrgId(), oldBuild);
                if (oldBuild.getIsParking().equals(IsDeleteEnum.NO.getKey())){
                    preBuildAvPriceMap.put(oldBuild.getOrgId(), oldBuild.getAveragePriceHouse());
                }else{
                    preBuildAvPriceMap.put(oldBuild.getOrgId(), oldBuild.getAveragePriceParking());
                }
            }
        }

        //创建新版本
        PriceVersionBackups priceVersionBackups = new PriceVersionBackups();
        BeanUtils.copyProperties(oldPriceVersion, priceVersionBackups);
        priceVersionBackups.setId(UUIDUtils.create());
        priceVersionBackups.setVersionId(oldPriceVersion.getId());
        priceVersionBackups.setUpdateTime(now);

        if(StringUtils.isNotEmpty(source) && source.equals("pano")){
            oldPriceVersion.setVersionLable(2);
            oldPriceVersion.setRemake("楼栋计划变动");
            priceVersionBackups.setVersionLable(2);
            priceVersionBackups.setBackupsExplain("楼栋计划变动:"+instId);
        }else if(StringUtils.isNotEmpty(source) && source.equals("area")){
            oldPriceVersion.setVersionLable(1);
            oldPriceVersion.setRemake("主数据变动");
            priceVersionBackups.setVersionLable(1);
            priceVersionBackups.setBackupsExplain("楼栋计划变动:"+instId);
        }else if(StringUtils.isNotEmpty(source) && source.equals("plan")){
            oldPriceVersion.setVersionLable(7);
            oldPriceVersion.setRemake("规划货值变动");
            priceVersionBackups.setVersionLable(7);
            priceVersionBackups.setBackupsExplain("规划货值变动:");
        }

        oldPriceVersion.setSourceAreaVersionStage(mdmProductWarPlanBO.getSourceAreaStage());
        oldPriceVersion.setSourceAreaVersionNum(mdmProductWarPlanBO.getSourceAreaNum());
        oldPriceVersion.setSourceAreaCreatedTime(mdmProductWarPlanBO.getSourceAreaCreatedTime());
        oldPriceVersion.setSourceAreaSysCreatedTime(mdmProductWarPlanBO.getSourceAreaSysCreatedTime());

        oldPriceVersion.setSourceGroupVersionStage(mdmProductWarPlanBO.getSourceGroupStage());
        oldPriceVersion.setSourceGroupVersionCode(mdmProductWarPlanBO.getSourceGroupNum());
        oldPriceVersion.setSourceGroupApprovalTime(mdmProductWarPlanBO.getSourceGroupApproval());
        oldPriceVersion.setSourceGroupCreateTime(mdmProductWarPlanBO.getSourceGroupSysCreatedTime());

        String sourceAreaDetail = "["+mdmProductWarPlanBO.getSourceAreaStage()+"&"+mdmProductWarPlanBO.getSourceAreaNum()+"&"+mdmProductWarPlanBO.getSourceAreaCreatedTime()+"]";
        String sourceOrgDetail = "["+mdmProductWarPlanBO.getSourceGroupStage()+"&"+mdmProductWarPlanBO.getSourceGroupNum()+"&"+mdmProductWarPlanBO.getSourceGroupApproval()+"]";
        oldPriceVersion.setSourceArea(sourceAreaDetail+"-"+sourceOrgDetail);
        oldPriceVersion.setSourceAreaDetail("["+ DateUtils.dateToString(LocalDateTimeUtils.convertLDTToDate(mdmProductWarPlanBO.getProjectFItems().getCreatDate()),
                DateUtils.DATE_KEY_SMALL_STR) +"]-["+mdmProductWarPlanBO.getProjectFItems().getVersionStage()+"]-["+mdmProductWarPlanBO.getProjectFItems().getVersionNum()+"]");

        oldPriceVersion.setSourcePlan(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
        oldPriceVersion.setSourcePlanDetail("["+DateUtils.dateToString(LocalDateTimeUtils.convertLDTToDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate()) ,
                DateUtils.DATE_KEY_SMALL_STR) + "]-[" +  panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType() +"]-[" +
                panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion()+"]");
        oldPriceVersion.setSourcePanoVersionType(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType());
        oldPriceVersion.setSourcePanoPlanVersion(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());
        oldPriceVersion.setSourcePanoCreatedDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate());

        oldPriceVersion.setUpdateTime(now);

        //如果版本是编制中，则将版本变为代编制
        String oldVersionState = oldPriceVersion.getVersionState();
        if(oldPriceVersion.getVersionState().equals(VersionStatusEnum.ORGANIZATION.getKey())){
            oldPriceVersion.setVersionState(VersionStatusEnum.NOTPREPARED.getKey());
        }

        //创建分期
        PriceValueOrg projectOrg = createStageValueInfo(now, mdmStage, oldPriceVersion.getId());

        //创建组团
        Map<String, PriceValueOrg> groupMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> groupInsertMap = new HashMap<String, PriceValueOrg>();
        List<MdmBuildAreaDetailBO> groupItems = mdmProductWarPlanBO.getGroupItems();
        for(MdmBuildAreaDetailBO groupItem : groupItems){
            dynamicVersionGroupItemInfo(now, oldPriceVersion, projectOrg, groupMap, groupInsertMap, groupItem);
        }

        //创建产品构成
        Map<String, PriceValueOrg> productMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> productInsertMap = new HashMap<String, PriceValueOrg>();
        List<MdmBuildAreaDetailBO> productItems = mdmProductWarPlanBO.getProductItems();

        //寻找上级分类
        dynamicVersionProductToDic(now, oldPriceVersion, groupMap, productMap, productInsertMap, productItems);

        //创建楼栋
        List<String> parkingBuildList = new ArrayList<>();
        List<PriceValueOrg> buildList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> notSalyTypeList = new ArrayList<PriceValueOrg>();
        for(MdmBuildAreaDetailBO buildItem : mdmProductWarPlanBO.getBuildItems()){
            dynamicVersionBuildItemInfo(oldPriceVersion, now, panoplanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, productMap, parkingBuildList, buildList, notSalyTypeList, buildItem);
        }

        //查看取数系统
        Map<String, PriceValueOrg> soldParkingMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> notSoldParkingOrgMap = new HashMap<String, PriceValueOrg>();
        Map<String, Map<String ,PriceValueOrg>> houseOrgMap = new HashMap<String, Map<String ,PriceValueOrg>>();
        Map<String, BigDecimal> areaMap = new HashMap<>();
        Map<String, Integer> numMap = new HashMap<>();

        //自持信息
        Map<String, Integer> zcParkingNumMap = new HashMap<>();//楼栋下自持房源套数
        Map<String, BigDecimal> zcParkingPriceMap = new HashMap<>();//楼栋下自持房源面积

        //收集面积段
        if (fetchSysCode.equals(FetchNnumberEnum.MY.getKey())){
        	//TODO 明源签约数据改成ESB下发，生产上线此处projectFid应改成 mdmStage.getKingdeeProjectfId()
            Map<String, Map> houseParkMap = myCollectHouse(projectFid, mdmStage.getKingdeeProjectfId(), parkingBuildList, preBuildAvPriceMap, now,null);
            soldParkingMap = houseParkMap.get("soldParkingMap");
            notSoldParkingOrgMap = houseParkMap.get("notSoldParkingOrgMap");
            houseOrgMap = houseParkMap.get("houseOrgMap");
            areaMap = houseParkMap.get("areaMap");
            numMap = houseParkMap.get("numMap");

            zcParkingNumMap = houseParkMap.get("zcParkingNumMap");
            zcParkingPriceMap = houseParkMap.get("zcParkingPriceMap");
        }else if(fetchSysCode.equals(FetchNnumberEnum.NOS.getKey())){
            Map<String, Map> houseParkMap = nosCollectHouse(mdmStage.getKingdeeProjectfId(), now,null);
            soldParkingMap = houseParkMap.get("soldParkingMap");
            houseOrgMap = houseParkMap.get("houseOrgMap");
            areaMap = houseParkMap.get("areaMap");
            numMap = houseParkMap.get("numMap");
        }

        //是否有销售货值
        if (CollectionUtils.isNotEmpty(houseOrgMap) || CollectionUtils.isNotEmpty(soldParkingMap) || CollectionUtils.isNotEmpty(notSoldParkingOrgMap)){
            oldPriceVersion.setIsContainSale(IsDeleteEnum.YES.getKey());
        }else{
            oldPriceVersion.setIsContainSale(IsDeleteEnum.NO.getKey());
        }

        List<PriceValueOrg> buildInsertList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> hoseSoleList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> sortParkList = new ArrayList<PriceValueOrg>();

        //赋值楼栋货值
        for (PriceValueOrg buildOrg : buildList){
            dynamicVersionBuildToOtherItemInfo(now, fetchSysCode, preSaleParkMap, preHouseMap, preBuildMap, oldPriceVersion, soldParkingMap, notSoldParkingOrgMap, houseOrgMap, areaMap, numMap, zcParkingNumMap, zcParkingPriceMap, buildInsertList, hoseSoleList, sortParkList, buildOrg);
        }

        //货值汇总
        List<PriceValueOrg> groupInsertList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> productInsertList = new ArrayList<PriceValueOrg>();
        if (CollectionUtils.isNotEmpty(buildInsertList)){
            dynamicVersionSumInfo(projectOrg, groupInsertMap, productInsertMap, buildInsertList, groupInsertList, productInsertList);
        }
        List<PriceValueOrg> projectList = Arrays.asList(projectOrg);

        //保存
        priceVersionService.refreshSaveInfo(oldPriceVersion,projectList,groupInsertList,productInsertList,buildInsertList,hoseSoleList,sortParkList,now);

        try{
            priceVersionBackupsService.refreshSaveInfo(oldPriceVersion,priceVersionBackups,now);
        }catch (Exception e){
            logger.error("################ refresh price versionBackups error : "+e);
        }

        try{
            String title = "货值上游变动刷新版本:";
            if(source!= null && source.equals(Constants.PANO)){
                title = title + "楼栋计划变更";
            }else if(source!= null && source.equals(Constants.MDM)){
                title = title + "主数据楼栋业态面积变更";
            }else if(source!= null && source.equals(Constants.PLAN)){
                title = title + "规划货值变更";
            }
            versionLogService.saveVersionLogInfo(oldPriceVersion.getProjectId(), oldPriceVersion.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), VersionEventEnum.SYS_REFRESH.getKey(), oldPriceVersion.getId(), VersionNameUtils.getVersionName(oldPriceVersion), oldVersionState,
                    oldPriceVersion.getVersionState(), "1", instId, Constants.SYS, now, title, isDifferenceList.toString(), IsDeleteEnum.NO.getKey(), Constants.SYS, now);
        }catch (Exception e){
            logger.error("################ refresh price version versionLog error : "+e);
        }

        logger.info("###########################    priceValueRefresh end:"+LocalDateTime.now());
    }

    private void panoTimeItemDetailChangeInfo(LocalDateTime now, PanoPlanCastDecisionBO panoPlanCastDecisionBO, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, PriceVersion newestDynamicPriceVersion) {
        newestDynamicPriceVersion.setSourcePlan(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
        newestDynamicPriceVersion.setSourcePlanDetail("["+ DateUtils.dateToString(LocalDateTimeUtils.convertLDTToDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate()) ,
                DateUtils.DATE_KEY_SMALL_STR) + "]-[" +  panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType() +"]-[" +
                panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion()+"]");
        newestDynamicPriceVersion.setSourcePanoVersionType(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType());
        newestDynamicPriceVersion.setSourcePanoPlanVersion(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());
        newestDynamicPriceVersion.setSourcePanoCreatedDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate());
        newestDynamicPriceVersion.setUpdateTime(now);

        List<PriceValueOrg> buildList = new ArrayList<PriceValueOrg>();
        QueryWrapper<PriceValueOrg> buildWrapper = new QueryWrapper<PriceValueOrg>();
        buildWrapper.eq("version_id", newestDynamicPriceVersion.getId())
                .eq("type", OrgTypeEunm.ORG_BUILD.getKey())
                .eq("is_delete", IsDeleteEnum.NO.getKey());
        List<PriceValueOrg> buildOrgs = priceValueOrgMapper.selectList(buildWrapper);
        if (CollectionUtils.isNotEmpty(buildOrgs)){
            for (PriceValueOrg buildOrg : buildOrgs){
                String orgId = buildOrg.getOrgId();

                buildOrg.setOpenTime(openTimeMap.get(orgId));
                buildOrg.setOpenTimeActual(openTimeActualMap.get(orgId));
                buildOrg.setSupplyTime(supplyTimeMap.get(orgId));
                buildOrg.setSupplyTimeActual(supplyTimeActualMap.get(orgId));
                buildOrg.setSupplyTimeVirtual(supplyTimeVirtualMap.get(orgId));
                buildOrg.setAdvanceSaleTime(advanceSaleTimeMap.get(orgId));
                buildOrg.setAdvanceSaleTimeActual(advanceSaleTimeActualMap.get(orgId));
                buildOrg.setOpenSaleTime(openSaleTimeMap.get(orgId));
                buildOrg.setOpenSaleTimeActual(openSaleTimeActualMap.get(orgId));
                buildOrg.setCappingTime(cappingTimeMap.get(orgId));
                buildOrg.setCappingTimeActual(cappingTimeActualMap.get(orgId));
                buildOrg.setCompletedTime(completedTimeMap.get(orgId));
                buildOrg.setCompletedTimeActual(completedTimeActualMap.get(orgId));
                buildOrg.setCarryOverTime(carryOverTimeMap.get(orgId));
                buildOrg.setCarryOverTimeActual(carryOverTimeActualMap.get(orgId));
                buildOrg.setActualDeliveryTime(actualDeliveryTimeMap.get(orgId));
                buildOrg.setActualDeliveryTimeActual(actualDeliveryTimeActualMap.get(orgId));
                buildOrg.setContractDeliveryTime(contractDeliveryTimeMap.get(orgId));
                buildOrg.setContractDeliveryTimeActual(contractDeliveryTimeActualMap.get(orgId));

                LocalDateTime ghshTime = supplyTimeVirtualMap.get(orgId);
                if (ghshTime != null) {
                    if (now.isBefore(ghshTime)) {
                        buildOrg.setIsSupply(SupplyEnum.NO.getKey());
                    } else {
                        buildOrg.setIsSupply(SupplyEnum.YES.getKey());
                    }
                } else {
                    ghshTime = supplyTimeActualMap.get(orgId);
                    if (ghshTime != null) {
                        if (now.isBefore(ghshTime)) {
                            buildOrg.setIsSupply(SupplyEnum.NO.getKey());
                        } else {
                            buildOrg.setIsSupply(SupplyEnum.YES.getKey());
                        }
                    } else {
                        buildOrg.setIsSupply(SupplyEnum.NO.getKey());
                    }
                }

                buildList.add(buildOrg);
            }

            priceBuildSaveInfo(newestDynamicPriceVersion, buildList);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    private void priceBuildSaveInfo(PriceVersion newestDynamicPriceVersion, List<PriceValueOrg> buildList) {
        priceVersionMapper.updateByPrimaryKeySelective(newestDynamicPriceVersion);

        if (CollectionUtils.isNotEmpty(buildList)) {
            priceValueOrgMapper.updateBatch(buildList);
        }
    }

    private void versionCreateOrRefreshVerification(String projectFid, String source, String instId, LocalDateTime now, MdmStage mdmStage, PanoPlanCastDecisionBO panoPlanCastDecisionBO, MdmBuildAreaBO mdmProductWarPlanBO, Map<String, PanoplanBuildPlanItem> panoplanItemMap, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, PriceVersion newestDynamicPriceVersion, List<PriceValueCompareVO> buildCompareVOList, String newestversionId, String versionType) {
        IdmUser sysUser = new IdmUser();
        sysUser.setAlias(Constants.SYS);
        sysUser.setUsercn(Constants.SYS_NAME);

        //查看货值版本是否有被供货确认使用
        boolean isComfirm = supplyPlanVersionService.supplyIsComfirm(newestDynamicPriceVersion.getId());
        if (isComfirm){
            //货值自动生成新版本
            String versionId = createSysDynamicVersion(projectFid, VersionTypeEunm.DYNAMIC.getKey(), VersionCreateEnum.AUTOMATICCREATE.getKey(), sysUser, source.equals("pano")?2:1, instId, null, null);

            noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_CREATE:Constants.NOTICE_MDM_CREATE, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, versionId, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());

            supplyPlanVersionService.createSupplyPlanVersion(versionId, versionType, Constants.SYS);
        }else{
            //查看货值版本是否有被签约使用
            Map<String, Boolean> signMap = signPlanVersionService.priceBoolean(Arrays.asList(newestDynamicPriceVersion.getId()));
            Boolean isSign = signMap.get(newestDynamicPriceVersion.getId());
            if (isSign){
                //货值自动生成新版本
                String versionId = createSysDynamicVersion(projectFid, VersionTypeEunm.DYNAMIC.getKey(), VersionCreateEnum.AUTOMATICCREATE.getKey(), sysUser, source.equals("pano")?2:1, instId, null, null);

                noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_CREATE:Constants.NOTICE_MDM_CREATE, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, versionId, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());

                supplyPlanVersionService.createSupplyPlanVersion(versionId, versionType, Constants.SYS);
            }else{

                //查看货值版本是否封板
                Integer isFinalization = newestDynamicPriceVersion.getIsFinalization();
                if (isFinalization != null && isFinalization.equals(IsDeleteEnum.YES.getKey())){

                    //货值自动生成新版本
                    String versionId = createSysDynamicVersion(projectFid, VersionTypeEunm.DYNAMIC.getKey(), VersionCreateEnum.AUTOMATICCREATE.getKey(), sysUser, source.equals("pano")?2:1, instId, null, null);

                    noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_CREATE:Constants.NOTICE_MDM_CREATE, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, versionId, VersionTypeEunm.DYNAMIC.getKey(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());

                    supplyPlanVersionService.createSupplyPlanVersion(versionId, versionType, Constants.SYS);
                }else{
                    //货值刷新
                    priceValueRefreshInfo(projectFid, newestDynamicPriceVersion, panoPlanCastDecisionBO, mdmProductWarPlanBO, instId, source, buildCompareVOList);

                    noticeRecordProcessedInfo(source.equals(Constants.PANO)?Constants.NOTICE_PANO_REFRESH:Constants.NOTICE_MDM_REFRESH, source, now, mdmStage, panoPlanCastDecisionBO, mdmProductWarPlanBO, newestDynamicPriceVersion.getId(), newestDynamicPriceVersion.getVersionType(), ProcessingModeEnum.SYSTEM.getKey(), ProcessingStateEnum.PROCESSED.getKey(), VersionTypeEunm.DYNAMIC.getKey());

                    supplyPlanVersionService.createSupplyPlanVersion(newestversionId, versionType, Constants.SYS);
                }
            }
        }
    }

    private void noticeCreateAndHandle(String projectFid, String source, LocalDateTime now, MdmStage mdmStage, MdmProject mdmProject, PanoPlanCastDecisionBO panoPlanCastDecisionBO, MdmBuildAreaBO mdmProductWarPlanBO, String versionType, String noticeProcessingMode) {

        //查询代办信息
        List<SysNotice> notices = sysNoticeService.selectModeByProjectFidAndVersionType(projectFid, ModuleTypeEunm.PRICE.getKey(), versionType, ProcessingStateEnum.UNTREATED.getKey(),IsDeleteEnum.NO.getKey());

        //系统将该项目分期之前同类待办设置为无效待办，同时删除新门户该分期之前同类待办
        sysNoticeService.updateNoticeStateByStageIdAndType(projectFid, ModuleTypeEunm.PRICE.getKey(), versionType, ProcessingStateEnum.FAILURE.getKey(), Constants.SYS, now , IsDeleteEnum.NO.getKey());

        if(CollectionUtils.isNotEmpty(notices)){

            for(SysNotice notice : notices){
                String instanceId = notice.getPortalInstanceId();

                //删除门户代办消息
                if(StringUtils.isNotEmpty(instanceId)){
                    IdmUser idmUser = new IdmUser();
                    idmUser.setAlias(Constants.SYS);
                    idmUser.setUsercn(Constants.SYS_NAME);
                    commonService.updatePortalProcess(instanceId, OperatorTypeEnum.TRANSFERRED_TO_OFFICE.getKey(), idmUser, null);
                }
            }
        }

        //发送货值待办提醒,填报动态版货值
        SysNotice notice = new SysNotice();
        notice.setId(UUIDUtils.create());
        StringBuffer taskRemarke = new StringBuffer();

        if(versionType != null && versionType.equals(VersionTypeEunm.WARPLAN.getKey())){
            notice.setTaskType(ModuleTypeEunm.PRICE.getKey());
            notice.setTaskSource(VersionTypeEunm.WARPLAN.getKey());

            taskRemarke.append("[填报战规版货值]").append(mdmProject.getProjectName()).append("项目").append(mdmStage.getStageName())
                    .append("分期有了新版战规版");
            if (source.equals(Constants.PANO)){
                notice.setTaskName(Constants.NOTICE_PANO);
                notice.setAffectedVersionStage(NoticeAffectedEnum.PANO_CHANGE.getKey());
                notice.setReceivingVersionId(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
                notice.setReceivingVersionNo(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());

                taskRemarke.append("楼栋计划：").append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType())
                        .append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion()).append("-")
                        .append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate().toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd")))
                        .append("，请填报该分期战规版货值。");
            }else if(source.equals(Constants.MDM)){
                notice.setTaskName(Constants.NOTICE_MDM);
                notice.setAffectedVersionStage(NoticeAffectedEnum.AREA_CHANGE.getKey());
                notice.setReceivingVersionId(mdmProductWarPlanBO.getTimestampId());
                notice.setReceivingVersionNo(mdmProductWarPlanBO.getSourceAreaNum());

                taskRemarke.append("面积：").append(mdmProductWarPlanBO.getSourceAreaStage())
                        .append(mdmProductWarPlanBO.getSourceAreaNum()).append("-")
                        .append(mdmProductWarPlanBO.getSourceAreaSysCreatedTime().toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd")))
                        .append("，请填报该分期战规版货值。");
            }
        }else{
            notice.setTaskType(ModuleTypeEunm.PRICE.getKey());
            notice.setTaskSource(VersionTypeEunm.DYNAMIC.getKey());

            taskRemarke.append("[填报动态版货值]").append(mdmProject.getProjectName()).append("项目").append(mdmStage.getStageName())
                    .append("分期有了新版");
            if (source.equals(Constants.PANO)){
                notice.setTaskName(Constants.NOTICE_PANO);
                notice.setAffectedVersionStage(NoticeAffectedEnum.PANO_CHANGE.getKey());
                notice.setReceivingVersionId(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
                notice.setReceivingVersionNo(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());

                taskRemarke .append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType())
                        .append("楼栋计划：").append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType())
                        .append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion()).append("-")
                        .append(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate().toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd")))
                        .append("，请填报该分期动态版货值。");
            }else if(source.equals(Constants.MDM)){
                notice.setTaskName(Constants.NOTICE_MDM);
                notice.setAffectedVersionStage(NoticeAffectedEnum.AREA_CHANGE.getKey());
                notice.setReceivingVersionId(mdmProductWarPlanBO.getTimestampId());
                notice.setReceivingVersionNo(mdmProductWarPlanBO.getSourceAreaNum());

                taskRemarke .append(mdmProductWarPlanBO.getSourceAreaStage())
                        .append("面积：").append(mdmProductWarPlanBO.getSourceAreaStage())
                        .append(mdmProductWarPlanBO.getSourceAreaNum()).append("-")
                        .append(mdmProductWarPlanBO.getSourceAreaSysCreatedTime().toLocalDate().format(DateTimeFormatter.ofPattern("yyyyMMdd")))
                        .append("，请填报该分期动态版货值。");
            }
        }

        notice.setProcessingMode(noticeProcessingMode);
        notice.setProjectId(mdmStage.getProjectId());
        notice.setStagesId(mdmStage.getProjectFid());
        notice.setState(ProcessingStateEnum.UNTREATED.getKey());
        notice.setDescInfo(taskRemarke.toString());
        notice.setIsDelete(IsDeleteEnum.NO.getKey());
        notice.setCreateBy(Constants.SYS);
        notice.setCreateTime(now);

        //发送门户代办提醒
        String instanceId = sendBackLog(mdmStage.getProjectId(), mdmStage.getProjectFid(), taskRemarke.toString(), null);
        if (StringUtils.isNotEmpty(instanceId)){
            notice.setPortalInstanceId(instanceId);
        }

        sysNoticeService.save(notice);
    }

    private void noticeRecordProcessedInfo(String taskName, String source, LocalDateTime now, MdmStage mdmStage, PanoPlanCastDecisionBO panoPlanCastDecisionBO, MdmBuildAreaBO mdmProductWarPlanBO, String priceVersionId, String priceVersionType, String noticeProcessingMode, String processingState, String taskSource) {
        SysNotice notice = new SysNotice();
        notice.setId(UUIDUtils.create());
        notice.setTaskName(taskName);
        notice.setTaskType(ModuleTypeEunm.PRICE.getKey());
        notice.setTaskSource(taskSource);
        if (source.equals(Constants.PANO)){
            if(panoPlanCastDecisionBO != null){
                notice.setReceivingVersionId(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
                notice.setReceivingVersionNo(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());
            }
            notice.setAffectedVersionStage(NoticeAffectedEnum.PANO_CHANGE.getKey());
        }else if(source.equals(Constants.MDM)){
            if(mdmProductWarPlanBO != null){
                notice.setReceivingVersionId(mdmProductWarPlanBO.getTimestampId());
                notice.setReceivingVersionNo(mdmProductWarPlanBO.getSourceAreaNum());
            }
            notice.setAffectedVersionStage(NoticeAffectedEnum.AREA_CHANGE.getKey());
        }
        notice.setProcessingMode(noticeProcessingMode);
        notice.setAffectedValueVersionId(priceVersionId);
        notice.setProjectId(mdmStage.getProjectId());
        notice.setStagesId(mdmStage.getProjectFid());
        notice.setState(processingState);
        notice.setIsDelete(IsDeleteEnum.NO.getKey());
        notice.setCreateBy(Constants.SYS);
        notice.setCreateTime(now);

        if(processingState.equals(ProcessingStateEnum.PROCESSED.getKey())){
            notice.setHandlePerson(Constants.SYS);
            notice.setProcessingTime(now);
        }

        sysNoticeService.save(notice);
    }

    private void houseDescSortList(List<PriceValueOrg> houseList) {
        houseList.sort((a, b) -> {
            String aAreaPart = a.getAreaPart();
            String bAreaPart = b.getAreaPart();

            Integer aComStr = 0;
            Integer bComStr = 0;

            if (aAreaPart.equals(Constants.ORTHER_HOUSE_NAME)) {
                aComStr = -1;
            } else {
                String[] aAplitStr = aAreaPart.split("-");
                aComStr = Integer.valueOf(aAplitStr[0]);
            }

            if (bAreaPart.equals(Constants.ORTHER_HOUSE_NAME)) {
                bComStr = -1;
            } else {
                String[] bSplitStr = bAreaPart.split("-");
                bComStr = Integer.valueOf(bSplitStr[0]);
            }

            return bComStr.compareTo(aComStr);
        });
    }


    /***
     * 自动创建战规后货值版本
     * @param projectFid 分期id
     * @param versionType 版本类型
     * @param createVersionType 创建版本类型
     * @param alias 创建人
     * @param lable 创建类型
     * @param instId esb报文instId
     * @return 版本id
     */
    @Override
    public synchronized String createSysDynamicVersion(String projectFid, String versionType, String createVersionType, IdmUser alias, Integer lable, String instId, Integer removeNoticeRule, Integer type) {
        LocalDateTime now = LocalDateTime.now();

        //根据分期查询项目下所有分期
        List<String> stageIds = getStagesByStageId(projectFid);

        //查询指定分期信息
        MdmStage mdmStage = getMdmStageByStageId(projectFid);

        //版本生成规则校验
        strategyCreateVersionVerification(projectFid, versionType, createVersionType, stageIds, lable, removeNoticeRule, mdmStage, instId,type);

        //获取最新的战规版楼栋计划
        PanoPlanCastDecisionBO panoPlanCastDecisionBO = panoplanBuildPlanService.selectNewestWarPlanByFid(projectFid, versionType, IsDeleteEnum.NO.getKey());

        //获取最新的战规版楼栋面积
        MdmBuildAreaBO mdmProductWarPlanBO = buildAreaService.selectNewestByFid(projectFid, versionType, IsDeleteEnum.NO.getKey());
        if(mdmProductWarPlanBO == null){
            throw new MsgException(CodeEnum.NON_GROUPBLD_AREA);
        }

        //全景计划系统最新版楼栋计划项目树与主数据系统最新版面积版本项目树不匹配，不允许创建新版本；
        mdmToPanoGroupVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO);

        mdmToPanoProductVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO);

        Map<String, String> panoplanBuildPlanItemMap = new HashMap<>();
        Map<String, PanoplanBuildPlanItem> panoplanItemMap = new HashMap<>();
        mdmToPanoBuildVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO, panoplanBuildPlanItemMap, panoplanItemMap);

        //楼栋计划匹配节点
        Map<String, LocalDateTime> openTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeVirtualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        panoTimeItemNodeMapInfo(panoPlanCastDecisionBO, panoplanBuildPlanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap);

        //分期有可售或阶段性自持产品构成没有批次或供货日期时，不允许新建该分期价格版本
        buildBusinessTypeVerificationByNode(panoPlanCastDecisionBO, panoplanBuildPlanItemMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap);

        //查询取数系统
        LocalDateTime fetchTime = null;
        String fetchSysCode = null;
        String fetchSysId = null;
        SysProjectFetchNumber fetchNumber = sysProjectFetchNumberService.selectByFid(projectFid);
        if(fetchNumber != null){
            if(StringUtils.isNotEmpty(fetchNumber.getCountingSystemId())){
                fetchTime = fetchNumber.getEffectiveDate();
                fetchSysCode = fetchNumber.getCountingSystemId();
                fetchSysId = fetchNumber.getId();
                if(type != null && fetchSysCode.equals("nos")) {
               	 throw new MsgException(CodeEnum.NOS_NON_FETCH_NUMBERVERSIONS);
                }
            }else{
                throw new MsgException(CodeEnum.NON_FETCH_NUMBERVERSIONS);
            }
        }else{
            throw new MsgException(CodeEnum.NON_FETCH_NUMBERVERSIONS);
        }

        //操盘方式
        String market = getStagePartnerToMarket(mdmStage);

        //归属年月
        LocalDate ascriptionDate = LocalDate.now();
        Integer isFinalization = null;
        if(versionType.equals(VersionTypeEunm.DYNAMIC.getKey())){
            isFinalization = IsDeleteEnum.NO.getKey();
            int day = now.getDayOfMonth();
            int hour = now.getHour();
            if (day == Constants.ONE && hour <=  Constants.SIX){//一号
                ascriptionDate = ascriptionDate.minusMonths(1);
            }
        }else{
            ascriptionDate = null;
        }

        //查询上一版本信息，如果是动态版之查当月的
        String oldVersionId = "";
        String oldVersionNum = "";
        PriceVersion priceVersion = null;
        if(versionType.equals(VersionTypeEunm.DYNAMIC.getKey())) {
            priceVersion = priceVersionService.selectNewestVersionByFidAndDate(projectFid, Arrays.asList(versionType), Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey(), now);
            if(type != null && type.intValue() == 1) {
            	if(priceVersion == null ) {
            		 throw new MsgException(CodeEnum.NOT_DYNAMIC);
            	}
            }
        }else{
            priceVersion = priceVersionService.selectNewestVersionByFid(projectFid, versionType);
        }
        
        if(priceVersion != null){
            if (priceVersion.getVersionType().equals(VersionTypeEunm.DYNAMIC.getKey())){
                LocalDate preAscriptionDate = priceVersion.getAscriptionDate();
                if(preAscriptionDate != null){
                    Month preMonth = preAscriptionDate.getMonth();
                    Month month = ascriptionDate.getMonth();
                    if(preMonth.equals(month)){
                        oldVersionId = priceVersion.getId();
                        oldVersionNum = priceVersion.getVersionNum();
                    }
                }
            }else{
            	if(priceVersion.getVersionType().equals(VersionTypeEunm.WARPLAN.getKey()) && !createVersionType.equals(VersionCreateEnum.EXCEPTIONCREATE.getKey())) {
           		 	throw new MsgException(CodeEnum.EXIST_WARPLAN_VERSIONS);
            	}
                oldVersionId = priceVersion.getId();
                oldVersionNum = priceVersion.getVersionNum();
            }
        }

        //查询全盘最新货值（复制战规后最新货值版本）
        String sourceValueId = "";
        Map<String, PriceValueOrg> presaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已售车位
        Map<String, PriceValueOrg> prenotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已定价未售车位
        Map<String, PriceValueOrg> preSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版可售车位
        Map<String, PriceValueOrg> preNotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版未推售车位
        Map<String, List<PriceValueOrg>> preHouseMap = new HashMap<String, List<PriceValueOrg>>(); //上一版房源包
        Map<String, PriceValueOrg> preBuildMap = new HashMap<String, PriceValueOrg>(); //上一版楼栋
        Map<String, BigDecimal> preBuildAvPriceMap = new HashMap<String, BigDecimal>();//上一版楼栋均价
        PriceVersion newestPriceVersion = priceVersionService.getNewestPriceVersion(mdmStage.getProjectFid());
        if(newestPriceVersion != null) {
            sourceValueId = dynamicVersionPreOrgInfo(sourceValueId, presaleParkMap, prenotSaleParkMap, preSaleParkMap, preNotSaleParkMap, preHouseMap, preBuildMap, preBuildAvPriceMap, newestPriceVersion);
        }

        //创建新版本
        PriceVersion newVersion = createVersionInfo(projectFid, versionType, createVersionType, alias.getAlias(), mdmStage, ascriptionDate, oldVersionId, oldVersionNum, lable,
                mdmProductWarPlanBO, panoPlanCastDecisionBO, isFinalization, sourceValueId, fetchTime, fetchSysCode, fetchSysId, market, now,type);

        //创建分期
        PriceValueOrg projectOrg = createStageValueInfo(now, mdmStage, newVersion.getId());

        //创建组团
        Map<String, PriceValueOrg> groupMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> groupInsertMap = new HashMap<String, PriceValueOrg>();
        List<MdmBuildAreaDetailBO> groupItems = mdmProductWarPlanBO.getGroupItems();
        for(MdmBuildAreaDetailBO groupItem : groupItems){
            dynamicVersionGroupItemInfo(now, newVersion, projectOrg, groupMap, groupInsertMap, groupItem);
        }

        //创建产品构成
        Map<String, PriceValueOrg> productMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> productInsertMap = new HashMap<String, PriceValueOrg>();
        List<MdmBuildAreaDetailBO> productItems = mdmProductWarPlanBO.getProductItems();

        //寻找产品构成上级分类
        dynamicVersionProductToDic(now, newVersion, groupMap, productMap, productInsertMap, productItems);

        //创建楼栋
        List<String> parkingBuildList = new ArrayList<>();
        List<PriceValueOrg> buildList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> notSalyTypeList = new ArrayList<PriceValueOrg>();
        for(MdmBuildAreaDetailBO buildItem : mdmProductWarPlanBO.getBuildItems()){
            dynamicVersionBuildItemInfo(newVersion, now, panoplanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, productMap, parkingBuildList, buildList, notSalyTypeList, buildItem);
        }

        //判断楼栋下经营方式是否全部为不可售，如果是的话则不能创建版本
//        if(notSalyTypeList.size() == buildList.size()){
//            throw new MsgException(CodeEnum.NON_BUILD_SALY_TYPE_ERROR);
//        }

        //查看取数系统
        Map<String, PriceValueOrg> soldParkingMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> notSoldParkingOrgMap = new HashMap<String, PriceValueOrg>();
        Map<String, Map<String ,PriceValueOrg>> houseOrgMap = new HashMap<String, Map<String ,PriceValueOrg>>();
        Map<String, BigDecimal> areaMap = new HashMap<>();
        Map<String, Integer> numMap = new HashMap<>();

        //自持信息
        Map<String, Integer> zcParkingNumMap = new HashMap<>();//楼栋下自持房源套数
        Map<String, BigDecimal> zcParkingPriceMap = new HashMap<>();//楼栋下自持房源面积

        //收集面积段
        if (fetchSysCode.equals(FetchNnumberEnum.MY.getKey())){
        	//TODO 明源签约数据改成ESB下发，生产上线此处projectFid应改成 mdmStage.getKingdeeProjectfId()
            Map<String, Map> houseParkMap = myCollectHouse(projectFid, mdmStage.getKingdeeProjectfId(), parkingBuildList, preBuildAvPriceMap, now,null);
            soldParkingMap = houseParkMap.get("soldParkingMap");
            notSoldParkingOrgMap = houseParkMap.get("notSoldParkingOrgMap");
            houseOrgMap = houseParkMap.get("houseOrgMap");
            areaMap = houseParkMap.get("areaMap");
            numMap = houseParkMap.get("numMap");

            zcParkingNumMap = houseParkMap.get("zcParkingNumMap");
            zcParkingPriceMap = houseParkMap.get("zcParkingPriceMap");
        }else if(fetchSysCode.equals(FetchNnumberEnum.NOS.getKey())){
            Map<String, Map> houseParkMap = nosCollectHouse(mdmStage.getKingdeeProjectfId(), now,null);
            soldParkingMap = houseParkMap.get("soldParkingMap");
            houseOrgMap = houseParkMap.get("houseOrgMap");
            areaMap = houseParkMap.get("areaMap");
            numMap = houseParkMap.get("numMap");
        }

        //是否有销售货值
        if (CollectionUtils.isNotEmpty(houseOrgMap) || CollectionUtils.isNotEmpty(soldParkingMap) || CollectionUtils.isNotEmpty(notSoldParkingOrgMap)){
            newVersion.setIsContainSale(IsDeleteEnum.YES.getKey());
        }else{
            newVersion.setIsContainSale(IsDeleteEnum.NO.getKey());
        }

        //创建战规版货值版本校验：检查历史版本是否有过一房一价的版本 或者 归集明源/NOS是否有销售数据，
        // 如果有，检查是否有大定价或动态版版本，
        // 如果没有，则不能创建战规版货值。
        if(newVersion.getVersionType().equals(VersionTypeEunm.WARPLAN.getKey())) {
            dynamicVersionStrategyVerification(projectFid, newVersion);
        }

        List<PriceValueOrg> buildInsertList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> hoseSoleList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> sortParkList = new ArrayList<PriceValueOrg>();

        //赋值楼栋货值
         for (PriceValueOrg buildOrg : buildList) {
            dynamicVersionBuildToOtherItemInfo(now, fetchSysCode, preSaleParkMap, preHouseMap, preBuildMap, newVersion, soldParkingMap, notSoldParkingOrgMap, houseOrgMap, areaMap, numMap, zcParkingNumMap, zcParkingPriceMap, buildInsertList, hoseSoleList, sortParkList, buildOrg);
        }

        //货值汇总
        List<PriceValueOrg> groupInsertList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> productInsertList = new ArrayList<PriceValueOrg>();
        if (CollectionUtils.isNotEmpty(buildInsertList)){
            dynamicVersionSumInfo(projectOrg, groupInsertMap, productInsertMap, buildInsertList, groupInsertList, productInsertList);
        }
        List<PriceValueOrg> projectList = Arrays.asList(projectOrg);

        //测试保存
        priceVersionService.saveInfo(newVersion,projectList,groupInsertList,productInsertList,buildInsertList,hoseSoleList,sortParkList);

        //处理代办信息
        priceHandleNoticeInfo(projectFid, versionType, createVersionType, alias, now);

        //版本日志
        priceVersionLogInfo(createVersionType, instId, now, mdmStage, newVersion, alias.getAlias());

        return newVersion.getId();
    }

	protected void dynamicVersionBuildToOtherItemInfo(LocalDateTime now, String fetchSysCode, Map<String, PriceValueOrg> preSaleParkMap, Map<String, List<PriceValueOrg>> preHouseMap, Map<String, PriceValueOrg> preBuildMap, PriceVersion newVersion, Map<String, PriceValueOrg> soldParkingMap, Map<String, PriceValueOrg> notSoldParkingOrgMap, Map<String, Map<String, PriceValueOrg>> houseOrgMap, Map<String, BigDecimal> areaMap, Map<String, Integer> numMap, Map<String, Integer> zcParkingNumMap, Map<String, BigDecimal> zcParkingPriceMap, List<PriceValueOrg> buildInsertList, List<PriceValueOrg> hoseSoleList, List<PriceValueOrg> sortParkList, PriceValueOrg buildOrg) {
        String buildId = buildOrg.getId();
        String versionId = buildOrg.getVersionId();
        String buildOrgId = buildOrg.getOrgId();
        Integer isParking = buildOrg.getIsParking();
        Integer buildNum = buildOrg.getNum() == null ? 0 : buildOrg.getNum();
        BigDecimal buildArea = buildOrg.getSaleArea() == null ? new BigDecimal(0) : buildOrg.getSaleArea();
        String businessType = buildOrg.getBusinessType();

        //如果楼栋是 不可租售 或 可租，则不复制信息
        if (businessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()) || businessType.equals(SalyTypeEnum.RENTED.getKey())) {
            buildInsertList.add(buildOrg);
            return;
        }

        //赋值上版本楼栋信息
        PriceValueOrg oldBuildOrg = preBuildMap.get(buildOrgId);
        if (oldBuildOrg != null) {
            buildOrg.setAveragePriceParking(oldBuildOrg.getAveragePriceParking());
            buildOrg.setAveragePriceHouse(oldBuildOrg.getAveragePriceHouse());

            if (isParking == IsDeleteEnum.YES.getKey()) {
                buildOrg.setNotCommodityValue(BigDecimalMUL(oldBuildOrg.getAveragePriceParking(), new BigDecimal(buildNum)));
                buildOrg.setCommodityValue(oldBuildOrg.getCommodityValue());
            } else {
                buildOrg.setHouseCommodityValue(BigDecimalMUL(oldBuildOrg.getAveragePriceHouse(), buildOrg.getSaleArea()));
            }
        }

        //车位信息
        if (isParking == IsDeleteEnum.YES.getKey()) {
            parkingCollectInfo(now, preSaleParkMap, preBuildMap, soldParkingMap, notSoldParkingOrgMap, numMap, zcParkingNumMap, zcParkingPriceMap, sortParkList, buildOrg, buildId, versionId, buildOrgId, buildNum, buildInsertList);
        } else {
            //归集收集房源包
            Map<String, PriceValueOrg> roomPriceValueOrgMap = houseOrgMap.get(buildOrgId);

            if (fetchSysCode.equals(FetchNnumberEnum.NOS.getKey()) || CollectionUtils.isEmpty(roomPriceValueOrgMap)) {
                //部分归集面积段
                areaPartCollectInfo(now, preHouseMap, newVersion.getId(), houseOrgMap, buildInsertList, hoseSoleList, buildOrg, buildId, buildOrgId, buildNum, buildArea, oldBuildOrg, numMap, areaMap);
            } else {
                //全部归集面积段
                allAreaPartCollectInfo(areaMap, numMap, buildInsertList, hoseSoleList, buildOrg, buildId, versionId, buildOrgId, roomPriceValueOrgMap);
            }
        }
    }

    protected void dynamicVersionStrategyVerification(String projectFid, PriceVersion newVersion) {
        PriceVersion saleValueHistoryVersion = priceVersionMapper.selectSaleValue(projectFid, IsDeleteEnum.NO.getKey());
        if(saleValueHistoryVersion != null || newVersion.getIsContainSale().equals(IsDeleteEnum.YES.getKey())){
            List<PriceVersion> priceVersionTypes = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(projectFid, Arrays.asList(VersionTypeEunm.GETPRICE.getKey(), VersionTypeEunm.DYNAMIC.getKey()),
                    Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(), VersionStatusEnum.ORGANIZATION.getKey() ,VersionStatusEnum.EXAMINEDAPPROVED.getKey(),
                            VersionStatusEnum.APPROVED.getKey(), VersionStatusEnum.FAILUREAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey()),
                    IsDeleteEnum.NO.getKey());
            if(CollectionUtils.isEmpty(priceVersionTypes)){
                throw new MsgException(CodeEnum.SALE_VALUE_ERROR);
            }
        }
    }

    private String dynamicVersionPreOrgInfo(String sourceValueId, Map<String, PriceValueOrg> presaleParkMap, Map<String, PriceValueOrg> prenotSaleParkMap, Map<String, PriceValueOrg> preSaleParkMap, Map<String, PriceValueOrg> preNotSaleParkMap, Map<String, List<PriceValueOrg>> preHouseMap, Map<String, PriceValueOrg> preBuildMap, Map<String, BigDecimal> preBuildAvPriceMap, PriceVersion newestPriceVersion) {
        String newestversionType = newestPriceVersion.getVersionType();
        if (!newestversionType.equals(VersionTypeEunm.INVESTMENT.getKey())) {
            sourceValueId = newestPriceVersion.getId();

            List<PriceValueCastDecisionAllOrgEXTBO> priceValueCastDecisionAllOrgEXTBOS = priceValueOrgMapper.selectHouseAndPark(newestPriceVersion.getId(), IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isNotEmpty(priceValueCastDecisionAllOrgEXTBOS)) {
                priceRefreshPreOrgInfo(presaleParkMap, prenotSaleParkMap, preSaleParkMap, preNotSaleParkMap, preHouseMap, priceValueCastDecisionAllOrgEXTBOS);
            }
        }

        List<PriceValueOrg> oldBuildList = priceValueOrgService.selectBuildByVersionId(newestPriceVersion.getId(), OrgTypeEunm.ORG_BUILD.getKey(), null, IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(oldBuildList)) {
            for (PriceValueOrg oldBuild : oldBuildList) {
                preBuildMap.put(oldBuild.getOrgId(), oldBuild);
                if (oldBuild.getIsParking().equals(IsDeleteEnum.NO.getKey())) {
                    preBuildAvPriceMap.put(oldBuild.getOrgId(), oldBuild.getAveragePriceHouse());
                } else {
                    preBuildAvPriceMap.put(oldBuild.getOrgId(), oldBuild.getAveragePriceParking());
                }
            }
        }
        return sourceValueId;
    }

    /**
     * 货值手动创建处理待办信息
     * @param projectFid 分期id
     * @param versionType 版本类型
     * @param alias 创建人
     * @param now 时间
     */
    private void priceHandleNoticeInfo(String projectFid, String versionType, String createVersionType, IdmUser alias, LocalDateTime now) {
        try{
            List<SysNotice> notices = sysNoticeService.selectModeByProjectFidAndVersionType(projectFid, ModuleTypeEunm.PRICE.getKey(), versionType, ProcessingStateEnum.UNTREATED.getKey(), IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isNotEmpty(notices)){
                for (SysNotice notice : notices){
                    notice.setState(ProcessingStateEnum.PROCESSED.getKey());
                    notice.setProcessingTime(now);
                    notice.setUpdateTime(now);
                    notice.setHandlePerson(Constants.SYS);
                    notice.setUpdateBy(Constants.SYS);
                    sysNoticeMapper.updateById(notice);

                    String instanceId = notice.getPortalInstanceId();

                    //删除门户代办消息
                    if(StringUtils.isNotEmpty(instanceId)){
                        commonService.updatePortalProcess(instanceId, OperatorTypeEnum.TRANSFERRED_TO_OFFICE.getKey(), alias, null);
                    }
                }
            }

            //手动创建战规版处理动态版待办(异常创建不处理)
            if(createVersionType.equals(VersionCreateEnum.MANUALCREATE.getKey())){
                if(versionType.equals(VersionTypeEunm.WARPLAN.getKey())){
                    List<SysNotice> dynamicNotices = sysNoticeService.selectModeByProjectFidAndVersionType(projectFid, ModuleTypeEunm.PRICE.getKey(), VersionTypeEunm.DYNAMIC.getKey(), ProcessingStateEnum.UNTREATED.getKey(), IsDeleteEnum.NO.getKey());
                    if (CollectionUtils.isNotEmpty(dynamicNotices)){
                        for (SysNotice notice : dynamicNotices){
                            notice.setState(ProcessingStateEnum.PROCESSED.getKey());
                            notice.setProcessingTime(now);
                            notice.setUpdateTime(now);
                            notice.setHandlePerson(Constants.SYS);
                            notice.setUpdateBy(Constants.SYS);
                            sysNoticeMapper.updateById(notice);

                            String instanceId = notice.getPortalInstanceId();

                            //删除门户代办消息
                            if(StringUtils.isNotEmpty(instanceId)){
                                commonService.updatePortalProcess(instanceId, OperatorTypeEnum.TRANSFERRED_TO_OFFICE.getKey(), alias, null);
                            }
                        }
                    }
                }
            }
        }catch (Exception e){
            logger.error("################ create price version notice error : "+e);
        }
    }

    /***
     * 货值归集明源房源信息
     * @param areaMap 面积集合
     * @param numMap 套数集合
     * @param buildInsertList 楼栋集合
     * @param hoseSoleList 可售房源集合
     * @param buildOrg 楼栋层级Org
     * @param buildId 楼栋id
     * @param versionId 版本id
     * @param buildOrgId 楼栋BldPrdId
     * @param roomPriceValueOrgMap 房源集合
     */
    private void allAreaPartCollectInfo(Map<String, BigDecimal> areaMap, Map<String, Integer> numMap, List<PriceValueOrg> buildInsertList, List<PriceValueOrg> hoseSoleList, PriceValueOrg buildOrg, String buildId, String versionId, String buildOrgId, Map<String, PriceValueOrg> roomPriceValueOrgMap) {
        int collectNum = 0; //归集总可售套数
        BigDecimal collectArea = new BigDecimal(0); //归集总可售面积
        BigDecimal collectPirce = new BigDecimal(0); //归集总可售金额

        int collectSoldNum = 0; //归集已售
        BigDecimal collectSoldArea = new BigDecimal(0); //归集已售
        BigDecimal collectSoldPirce = new BigDecimal(0); //归集已售

        int collectPricedNum = 0; //归集已定价未售
        BigDecimal collectPricedArea = new BigDecimal(0);//归集已定价未售
        BigDecimal collectPricedPirce = new BigDecimal(0); //归集已定价未售

        int collectZCNum = 0; //归集自持
        BigDecimal collectZCArea = new BigDecimal(0);  //归集自持
        BigDecimal collectZCPirce = new BigDecimal(0); //归集自持

        for (Map.Entry<String, PriceValueOrg> roomHouses : roomPriceValueOrgMap.entrySet()){
            PriceValueOrg roomValueOrg = roomHouses.getValue();
            roomValueOrg.setPid(buildId);
            roomValueOrg.setVersionId(versionId);

            hoseSoleList.add(roomValueOrg);

            collectNum = collectNum + (roomValueOrg.getRoomNum()==null?0:roomValueOrg.getRoomNum());
            collectArea = BigDecimalADD(collectArea, roomValueOrg.getSaleArea());
            collectPirce = BigDecimalADD(collectPirce, roomValueOrg.getHouseCommodityValue());

            collectSoldNum = collectSoldNum + (roomValueOrg.getRoomSold()==null?0:roomValueOrg.getRoomSold());
            collectSoldArea = BigDecimalADD(collectSoldArea, roomValueOrg.getAreaSold());
            collectSoldPirce = BigDecimalADD(collectSoldPirce, roomValueOrg.getPriceSold());

            collectPricedNum = collectPricedNum + (roomValueOrg.getRoomPriced()==null?0:roomValueOrg.getRoomPriced());
            collectPricedArea = BigDecimalADD(collectPricedArea, roomValueOrg.getAreaPriced());
            collectPricedPirce = BigDecimalADD(collectPricedPirce, roomValueOrg.getPricePriced());

            collectZCNum = collectZCNum + (roomValueOrg.getRoomZc()==null?0:roomValueOrg.getRoomZc());
            collectZCArea = BigDecimalADD(collectZCArea, roomValueOrg.getAreaZc());
            collectZCPirce = BigDecimalADD(collectZCPirce, roomValueOrg.getPriceRoomZc());
        }

        buildOrg.setNum(collectNum);
        buildOrg.setRoomNum(collectNum);
        buildOrg.setSaleArea(collectArea);
        buildOrg.setHouseCommodityValue(collectPirce);
        buildOrg.setAveragePriceHouse(bigDecimalDIV(collectPirce, collectArea));

        buildOrg.setRoomSold(collectSoldNum);
        buildOrg.setAreaSold(collectSoldArea);
        buildOrg.setPriceSold(collectSoldPirce);
        buildOrg.setRoomPriced(collectPricedNum);
        buildOrg.setAreaPriced(collectPricedArea);
        buildOrg.setPricePriced(collectPricedPirce);

        buildOrg.setRoomZc(collectZCNum);
        buildOrg.setAreaZc(collectZCArea);
        buildOrg.setPriceRoomZc(collectZCPirce);

        Integer totalNum = numMap.get(buildOrgId);
        buildOrg.setTotalNum(totalNum);

        BigDecimal totalArea = areaMap.get(buildOrgId);
        buildOrg.setTotalSaleArea(totalArea);

        buildOrg.setIsTotalCollect(IsDeleteEnum.YES.getKey());

        buildInsertList.add(buildOrg);
    }

    /**
     * 车位归集信息
     * @param now 时间
     * @param preSaleParkMap 上一版以售车位集合
     * @param preBuildMap 上一版楼栋集合
     * @param soldParkingMap 以售车位集合
     * @param notSoldParkingOrgMap 以定价未售车位集合
     * @param numMap 套数集合
     * @param zcParkingNumMap 自持车位集合
     * @param zcParkingPriceMap 自持车位金额集合
     * @param sortParkList 可售车位集合
     * @param buildOrg 楼栋层级Org
     * @param buildId 楼栋id
     * @param versionId 版本id
     * @param buildOrgId 楼栋BrdPrdId
     * @param buildNum 楼栋套数
     * @param buildInsertList 新增楼栋集合
     */
    public void parkingCollectInfo(LocalDateTime now, Map<String, PriceValueOrg> preSaleParkMap, Map<String, PriceValueOrg> preBuildMap, Map<String, PriceValueOrg> soldParkingMap, Map<String, PriceValueOrg> notSoldParkingOrgMap, Map<String, Integer> numMap, Map<String, Integer> zcParkingNumMap, Map<String, BigDecimal> zcParkingPriceMap, List<PriceValueOrg> sortParkList, PriceValueOrg buildOrg, String buildId, String versionId, String buildOrgId, Integer buildNum, List<PriceValueOrg> buildInsertList) {
        //总数
        Integer totalNum = 0;
        Integer totalCollectNum = numMap.get(buildOrgId)==null?0:numMap.get(buildOrgId);//归集车位楼栋总数
        if(totalCollectNum > buildNum){
            totalNum = totalCollectNum;
        }else{
            totalNum = buildNum;
        }

        int collectNum = 0; //归集总已售车位数量
        BigDecimal collectPirce = new BigDecimal(0); //归集总已售车位货值

        int saleSumNum = 0; //已售车位数量
        BigDecimal saleSumPrice = new BigDecimal(0); //已售车位金额

        int notSaleSumNum = 0; //已定价未售车位数量
        BigDecimal notSaleSumPrice = new BigDecimal(0); //已定价未售车位金额

        Integer zcParkingNum = zcParkingNumMap.get(buildOrgId)==null?0:zcParkingNumMap.get(buildOrgId);//自持车位数量
        BigDecimal zcParkingPrice = zcParkingPriceMap.get(buildOrgId)==null?new BigDecimal(0):zcParkingPriceMap.get(buildOrgId);//自持车位金额

        //归集已售车位
        if(CollectionUtils.isNotEmpty(soldParkingMap)){
            PriceValueOrg solePark = soldParkingMap.get(buildOrgId);
            if (solePark != null) {
                solePark.setPid(buildId);
                solePark.setVersionId(versionId);
                solePark.setTotalNum(totalNum);
                solePark.setIsSplit(IsDeleteEnum.YES.getKey());
                solePark.setIsParking(IsDeleteEnum.YES.getKey());
                sortParkList.add(solePark);

                buildOrg.setPriceSold(solePark.getPricePriced());
                buildOrg.setParkingSold(solePark.getParkingPriced());

                collectNum = collectNum + solePark.getParkingNum();
                collectPirce = BigDecimalADD(collectPirce, solePark.getNotCommodityValue());

                saleSumNum = saleSumNum + solePark.getParkingNum();
                saleSumPrice = BigDecimalADD(saleSumPrice, solePark.getNotCommodityValue());
            }
        }

        //归集已定价未售车位
        if(CollectionUtils.isNotEmpty(notSoldParkingOrgMap)){
            PriceValueOrg notSolePark = notSoldParkingOrgMap.get(buildOrgId);
            if (notSolePark != null) {
                notSolePark.setPid(buildId);
                notSolePark.setVersionId(versionId);
                notSolePark.setTotalNum(totalNum);
                notSolePark.setIsSplit(IsDeleteEnum.YES.getKey());
                notSolePark.setIsParking(IsDeleteEnum.YES.getKey());
                sortParkList.add(notSolePark);

                buildOrg.setPricePriced(notSolePark.getPricePriced());
                buildOrg.setParkingPriced(notSolePark.getParkingPriced());

                collectNum = collectNum + notSolePark.getParkingNum();
                collectPirce = BigDecimalADD(collectPirce, notSolePark.getNotCommodityValue());

                notSaleSumNum = notSaleSumNum + notSolePark.getParkingNum();
                notSaleSumPrice = BigDecimalADD(notSaleSumPrice, notSolePark.getNotCommodityValue());
            }
        }

        int subNum = buildNum - collectNum - zcParkingNum;
        if (subNum > 0){
            PriceValueOrg preBuildOrg = preBuildMap.get(buildOrgId);
            Integer preTotalSaleNum = 0;
            Integer preTotalZCNum = 0;
            if(preBuildOrg != null){
                preTotalSaleNum = preBuildOrg.getParkingNum()==null?0:preBuildOrg.getParkingNum();
                preTotalZCNum = preBuildOrg.getParkingZc()==null?0:preBuildOrg.getParkingZc();
            }

            //剩余未推售 = 新的主数据⻋位楼栋总⻋位数 - 上⼀版⻋位楼栋总可售⻋位数 - 上⼀版⻋位楼栋已定价⾃持⻋位数；
            Integer supNotSale = buildNum - preTotalSaleNum - preTotalZCNum;

            //如果剩余未推售 <0 时，剩余未推售 = 0
            if(supNotSale < 0){
                supNotSale = 0;
            }

            //新的可售未定价⻋位数 = 新的主数据⻋位楼栋总⻋位数 – 新归集的已售⻋位数 – 新归集的已定价未售⻋位数 - 新归集的已定价⾃持⻋位数 - 剩余未推售；
            Integer saleNum = buildNum - saleSumNum - notSaleSumNum - zcParkingNum - supNotSale;

            //如果新的可售未定价⻋位数 < 0，新的可售未定价⻋位数=0
            if(saleNum < 0){
                saleNum = 0;
            }

            //新的未推售⻋位数 = 新的主数据⻋位楼栋总⻋位数 – 新归集的已售⻋位数 – 新归集的已定价未售⻋位数- 新的可售未定价⻋位数 - 新归集的已定价⾃持⻋位数；
            Integer forsaleNum = buildNum - saleSumNum - notSaleSumNum - saleNum - zcParkingNum;

            // 如果新的未推售⻋位数 < 0，新的未推售⻋位数=0
            if(forsaleNum < 0){
                forsaleNum = 0;
            }

            //上一版可售车位信息
            BigDecimal preSaleAveragePriceParking = new BigDecimal(0);
            PriceValueOrg preSaleParkOrg = preSaleParkMap.get(buildOrgId);
            if (preSaleParkOrg != null){
                preSaleAveragePriceParking = preSaleParkOrg.getAveragePriceParking();
            }else{
                //没有上一版可售未定价车位均价的时候，使用上一版车位楼栋均价
                if(preBuildOrg != null){
                    preSaleAveragePriceParking = preBuildOrg.getAveragePriceParking();
                }else{
                    preSaleAveragePriceParking = new BigDecimal(0);
                }
            }

            //归集可售车位
            PriceValueOrg newSaleValueOrg = new PriceValueOrg();
            newSaleValueOrg.setId(UUIDUtils.create());
            newSaleValueOrg.setVersionId(versionId);
            newSaleValueOrg.setPid(buildId);
            newSaleValueOrg.setType(OrgTypeEunm.ORG_SALING_PARKING.getKey());
            newSaleValueOrg.setOrgCode(OrgTypeEunm.ORG_SALING_PARKING.getKey());
            newSaleValueOrg.setOrgName(OrgTypeEunm.ORG_SALING_PARKING.getValue());
            newSaleValueOrg.setNum(saleNum);
            newSaleValueOrg.setParkingNum(saleNum);
            newSaleValueOrg.setAveragePriceParking(preSaleAveragePriceParking);
            BigDecimal salePrice = BigDecimalMUL(preSaleAveragePriceParking, new BigDecimal(saleNum));
            newSaleValueOrg.setNotCommodityValue(salePrice);
            newSaleValueOrg.setIsParking(IsDeleteEnum.YES.getKey());
            newSaleValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
            newSaleValueOrg.setIsSplit(IsDeleteEnum.NO.getKey());
            newSaleValueOrg.setTotalNum(totalNum);
            newSaleValueOrg.setCreateTime(now);
            newSaleValueOrg.setUpdateTime(now);
            sortParkList.add(newSaleValueOrg);

            //归集待售车位
            BigDecimal notCollectPrice = new BigDecimal(0);
            if(forsaleNum > 0){
                PriceValueOrg newPriceValueOrg = new PriceValueOrg();
                newPriceValueOrg.setId(UUIDUtils.create());
                newPriceValueOrg.setVersionId(versionId);
                newPriceValueOrg.setPid(buildId);
                newPriceValueOrg.setType(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey());
                newPriceValueOrg.setOrgCode(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey());
                newPriceValueOrg.setOrgName(OrgTypeEunm.ORG_NOT_SALING_PARKING.getValue());
                newPriceValueOrg.setNum(forsaleNum);
                newPriceValueOrg.setForsaleParkingNum(forsaleNum);

                if(forsaleNum.equals(totalNum)){
                    notCollectPrice = BigDecimalMUL(preSaleAveragePriceParking, new BigDecimal(forsaleNum));
                    newPriceValueOrg.setAveragePriceParkingForsale(preSaleAveragePriceParking);
                }else{
                    notCollectPrice = BigDecimalMUL(buildOrg.getAveragePriceParking(), new BigDecimal(forsaleNum));
                    newPriceValueOrg.setAveragePriceParkingForsale(buildOrg.getAveragePriceParking());
                }

                newPriceValueOrg.setCommodityValue(notCollectPrice);
                newPriceValueOrg.setIsParking(IsDeleteEnum.YES.getKey());
                newPriceValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
                newPriceValueOrg.setIsSplit(IsDeleteEnum.NO.getKey());
                newPriceValueOrg.setTotalNum(totalNum);
                newPriceValueOrg.setCreateTime(now);
                newPriceValueOrg.setUpdateTime(now);
                sortParkList.add(newPriceValueOrg);
            }

            collectNum = saleNum + collectNum;
            collectPirce = BigDecimalADD(collectPirce, salePrice);
            buildOrg.setNotCommodityValue(collectPirce);
            buildOrg.setNum(collectNum+forsaleNum);
            buildOrg.setParkingNum(collectNum);
            buildOrg.setTotalNum(totalNum);
            buildOrg.setAveragePriceParking(bigDecimalDIV(
                    buildOrg.getNotCommodityValue(), new BigDecimal(buildOrg.getParkingNum())));
            buildOrg.setForsaleParkingNum(forsaleNum);
            buildOrg.setCommodityValue(notCollectPrice);
            buildOrg.setParkingSold(saleSumNum);
            buildOrg.setPriceSold(saleSumPrice);
            buildOrg.setParkingPriced(notSaleSumNum);
            buildOrg.setPricePriced(notSaleSumPrice);
            buildOrg.setParkingZc(zcParkingNum);
            buildOrg.setPriceParkingZc(zcParkingPrice);
        }else {
            //从新计算楼栋的面积、套数、均价、金额(货值)
            buildOrg.setNum(collectNum);
            buildOrg.setParkingNum(collectNum);
            buildOrg.setForsaleParkingNum(0);
            buildOrg.setNotCommodityValue(collectPirce);
            buildOrg.setCommodityValue(new BigDecimal(0));
            buildOrg.setAveragePriceParking(bigDecimalDIV(collectPirce, new BigDecimal(collectNum)));
            buildOrg.setParkingSold(saleSumNum);
            buildOrg.setPriceSold(saleSumPrice);
            buildOrg.setParkingPriced(notSaleSumNum);
            buildOrg.setPricePriced(notSaleSumPrice);
            buildOrg.setTotalNum(collectNum + zcParkingNum);
            buildOrg.setParkingZc(zcParkingNum);
            buildOrg.setPriceParkingZc(zcParkingPrice);
        }
        buildInsertList.add(buildOrg);
    }

    //创建货值版本信息
    public PriceVersion createVersionInfo(String projectFid, String versionType, String createVersionType, String alias, MdmStage mdmStage, LocalDate ascriptionDate, String oldVersionId, String oldVersionNum,
                                           Integer lable, MdmBuildAreaBO mdmProductWarPlanBO, PanoPlanCastDecisionBO panoPlanCastDecisionBO, Integer isFinalization, String sourceValueId,
                                           LocalDateTime fetchTime, String fetchSysCode, String fetchSysId, String market, LocalDateTime now,Integer batchAdjust) {
        PriceVersion newVersion = new PriceVersion();
        String newVersionNum = VersionUtils.bigVersionInc(oldVersionNum);
        newVersion.setPreVersionId(oldVersionId);
        newVersion.setPreVersionNum(oldVersionNum);
        newVersion.setId(UUIDUtils.create());
        newVersion.setProjectId(mdmStage.getProjectId());
        newVersion.setProjectfId(projectFid);
        newVersion.setStageName(mdmStage.getStageName());
        newVersion.setStageCode(mdmStage.getStageCode());

        if (versionType.equals(VersionTypeEunm.DYNAMIC.getKey())){
            DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMM");
            newVersion.setVersionName(df.format(ascriptionDate)+"月动态版"+newVersionNum);
        }else{
            newVersion.setVersionName(VersionTypeEunm.getValueByKey(versionType)+newVersionNum);
        }

        newVersion.setVersionNum(newVersionNum);
        newVersion.setVersionType(versionType);
        newVersion.setVersionCreateState(createVersionType);
        newVersion.setCreateBy(alias);

        String versionState = "";
        if(createVersionType.equals(VersionCreateEnum.MANUALCREATE.getKey()) ||
                createVersionType.equals(VersionCreateEnum.EXCEPTIONCREATE.getKey())){
            versionState = VersionStatusEnum.NOTPREPARED.getKey();
            newVersion.setVersionState(versionState);
        }else{
            newVersion.setVersionState(VersionStatusEnum.SYSGENERATION.getKey());
            newVersion.setVersionLable(lable);
            if(lable != null && lable == 1){
                newVersion.setRemake("主数据变动");
            }else if(lable != null && lable == 2){
                newVersion.setRemake("楼栋计划变动");
            }else if(lable != null && lable == 3){
                newVersion.setRemake("实际数据刷新");
            }else if (lable != null && lable == 4){
                newVersion.setRemake("定稿生成");
            }else if (lable != null && lable == 5){
                newVersion.setRemake("异常创建版本");
            }else if (lable != null && lable == 6){
                newVersion.setRemake("定稿创建月初版本");
            }else if(lable != null && lable == 7){
                newVersion.setRemake("明源调整规划货值生成");
            }else{
                newVersion.setRemake("创建版本");
            }
        }

        newVersion.setSourceAreaVersionStage(mdmProductWarPlanBO.getSourceAreaStage());
        newVersion.setSourceAreaVersionNum(mdmProductWarPlanBO.getSourceAreaNum());
        newVersion.setSourceAreaCreatedTime(mdmProductWarPlanBO.getSourceAreaCreatedTime());
        newVersion.setSourceAreaSysCreatedTime(mdmProductWarPlanBO.getSourceAreaSysCreatedTime());

        newVersion.setSourceGroupVersionStage(mdmProductWarPlanBO.getSourceGroupStage());
        newVersion.setSourceGroupVersionCode(mdmProductWarPlanBO.getSourceGroupNum());
        newVersion.setSourceGroupApprovalTime(mdmProductWarPlanBO.getSourceGroupApproval());
        newVersion.setSourceGroupCreateTime(mdmProductWarPlanBO.getSourceGroupSysCreatedTime());

        String sourceAreaDetail = "["+mdmProductWarPlanBO.getSourceAreaStage()+"&"+mdmProductWarPlanBO.getSourceAreaNum()+"&"+mdmProductWarPlanBO.getSourceAreaCreatedTime()+"]";
        String sourceOrgDetail = "["+mdmProductWarPlanBO.getSourceGroupStage()+"&"+mdmProductWarPlanBO.getSourceGroupNum()+"&"+mdmProductWarPlanBO.getSourceGroupApproval()+"]";
        newVersion.setSourceArea(sourceAreaDetail+"-"+sourceOrgDetail);
        newVersion.setSourceAreaDetail("["+ DateUtils.dateToString(LocalDateTimeUtils.convertLDTToDate(mdmProductWarPlanBO.getProjectFItems().getCreatDate()),
                DateUtils.DATE_KEY_SMALL_STR) +"]-["+mdmProductWarPlanBO.getProjectFItems().getVersionStage()+"]-["+mdmProductWarPlanBO.getProjectFItems().getVersionNum()+"]");

        newVersion.setSourcePlan(panoPlanCastDecisionBO.getPanoplanBuildPlan().getId());
        newVersion.setSourcePlanDetail("["+DateUtils.dateToString(LocalDateTimeUtils.convertLDTToDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate()) ,
                DateUtils.DATE_KEY_SMALL_STR) + "]-[" +  panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType() +"]-[" +
                panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion()+"]");
        newVersion.setSourcePanoVersionType(panoPlanCastDecisionBO.getPanoplanBuildPlan().getVersionType());
        newVersion.setSourcePanoPlanVersion(panoPlanCastDecisionBO.getPanoplanBuildPlan().getPlanVersion());
        newVersion.setSourcePanoCreatedDate(panoPlanCastDecisionBO.getPanoplanBuildPlan().getCreatedDate());

        newVersion.setIsFinalization(isFinalization);
        newVersion.setAscriptionDate(ascriptionDate);
        newVersion.setSourceValue(sourceValueId);
        newVersion.setCountingTime(fetchTime);
        newVersion.setCountingSystemCode(fetchSysCode);
        newVersion.setCountingSystemId(fetchSysId);
        newVersion.setIsMarket(market);
        newVersion.setIsDelete(IsDeleteEnum.NO.getKey());
        newVersion.setCreateTime(now);
        newVersion.setUpdateTime(now);
        if(batchAdjust != null) {
        	newVersion.setBatchAdjust(batchAdjust);
        }else {
        	newVersion.setBatchAdjust(IsDeleteEnum.NO.getKey());
        }

        return newVersion;
    }

    //创建楼栋
    public PriceValueOrg createBuildValueInfo(LocalDateTime now, Map<String, PanoplanBuildPlanItem> panoplanItemMap, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, String newVersionId, Map<String, PriceValueOrg> productMap, List<String> parkingBuildList, MdmBuildAreaDetailBO buildItem) {
        PriceValueOrg priceValueOrg = new PriceValueOrg();
        String buildId = UUIDUtils.create();
        priceValueOrg.setId(buildId);
        priceValueOrg.setVersionId(newVersionId);
        PriceValueOrg productOrg = productMap.get(buildItem.getGroupId() + "&" + buildItem.getProductCode());
        priceValueOrg.setPid(productOrg.getId());
        priceValueOrg.setType(OrgTypeEunm.ORG_BUILD.getKey());
        priceValueOrg.setOrgId(buildItem.getBldPrdId());
        priceValueOrg.setOrgCode(buildItem.getDesignBuildId());
        priceValueOrg.setOrgName(buildItem.getFormatBuildingName());

        if (StringUtils.isNotEmpty(buildItem.getBusinessType()) && StringUtils.isNotEmpty(buildItem.getBusinessTypeName())) {
            priceValueOrg.setBusinessType(buildItem.getBusinessType());
            priceValueOrg.setBusinessTypeName(buildItem.getBusinessTypeName());
        } else {
            throw new MsgException(CodeEnum.NON_EXISTENT_BUSINESSTYPE);
        }
        if (StringUtils.isNotEmpty(buildItem.getFreeType()) && StringUtils.isNotEmpty(buildItem.getFreeTypeName())) {
            priceValueOrg.setFreeType(buildItem.getFreeType());
            priceValueOrg.setFreeTypeName(buildItem.getFreeTypeName());
        } else {
            throw new MsgException(CodeEnum.NON_EXISTENT_FREETYPE);
        }
        if (StringUtils.isNotEmpty(buildItem.getProType()) && StringUtils.isNotEmpty(buildItem.getProTypeName())) {
            priceValueOrg.setProType(buildItem.getProType());
            priceValueOrg.setProTypeName(buildItem.getProTypeName());
        } else {
            throw new MsgException(CodeEnum.NON_EXISTENT_PROTYPE);
        }

        priceValueOrg.setSaleArea(buildItem.getTotalSaleArea() == null ? new BigDecimal(0) : buildItem.getTotalSaleArea());
        priceValueOrg.setNum(buildItem.getRoomNum() == null ? 0 : buildItem.getRoomNum());
        priceValueOrg.setAreaTotalSaleArea(buildItem.getTotalSaleArea());
        priceValueOrg.setAreaRoomNum(new BigDecimal(buildItem.getRoomNum() == null ? 0 : buildItem.getRoomNum()));

        priceValueOrg.setTotalNum(buildItem.getRoomNum() == null ? 0 : buildItem.getRoomNum());
        priceValueOrg.setTotalSaleArea(buildItem.getTotalSaleArea() == null ? new BigDecimal(0) : buildItem.getTotalSaleArea());

        //匹配时间节点
        String strCode = buildItem.getGroupId() + "&" + buildItem.getProductCode() + "&" + buildItem.getBldPrdId();
        priceValueOrg.setOpenTime(openTimeMap.get(strCode));
        priceValueOrg.setOpenTimeActual(openTimeActualMap.get(strCode));
        priceValueOrg.setSupplyTime(supplyTimeMap.get(strCode));
        priceValueOrg.setSupplyTimeActual(supplyTimeActualMap.get(strCode));
        priceValueOrg.setSupplyTimeVirtual(supplyTimeVirtualMap.get(strCode));
        priceValueOrg.setAdvanceSaleTime(advanceSaleTimeMap.get(strCode));
        priceValueOrg.setAdvanceSaleTimeActual(advanceSaleTimeActualMap.get(strCode));
        priceValueOrg.setOpenSaleTime(openSaleTimeMap.get(strCode));
        priceValueOrg.setOpenSaleTimeActual(openSaleTimeActualMap.get(strCode));
        priceValueOrg.setCappingTime(cappingTimeMap.get(strCode));
        priceValueOrg.setCappingTimeActual(cappingTimeActualMap.get(strCode));
        priceValueOrg.setCompletedTime(completedTimeMap.get(strCode));
        priceValueOrg.setCompletedTimeActual(completedTimeActualMap.get(strCode));
        priceValueOrg.setCarryOverTime(carryOverTimeMap.get(strCode));
        priceValueOrg.setCarryOverTimeActual(carryOverTimeActualMap.get(strCode));
        priceValueOrg.setActualDeliveryTime(actualDeliveryTimeMap.get(strCode));
        priceValueOrg.setActualDeliveryTimeActual(actualDeliveryTimeActualMap.get(strCode));
        priceValueOrg.setContractDeliveryTime(contractDeliveryTimeMap.get(strCode));
        priceValueOrg.setContractDeliveryTimeActual(contractDeliveryTimeActualMap.get(strCode));

        PanoplanBuildPlanItem panoplanItem = panoplanItemMap.get(buildItem.getGroupId() + "&" + buildItem.getProductCode() + "&" + buildItem.getBldPrdId());
        if (panoplanItem != null) {
            priceValueOrg.setPanoTotalRoomNum(panoplanItem.getTotalRoomNum());
            priceValueOrg.setPanoTotalSaleArea(panoplanItem.getTotalSaleArea());
            priceValueOrg.setPanoBatchRoomNum(panoplanItem.getBatchRoomNum());
            priceValueOrg.setPanoBatchSaleArea(panoplanItem.getBatchSaleArea());
            priceValueOrg.setPanoSalePark(panoplanItem.getSalePark());
            priceValueOrg.setPanoTotalBuildArea(panoplanItem.getTotalBuildArea());
            priceValueOrg.setPanoBatchBuildArea(panoplanItem.getBatchBuildArea());
        }

        priceValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
        priceValueOrg.setCreateTime(now);

        LocalDateTime ghshTime = supplyTimeVirtualMap.get(strCode);
        if (ghshTime != null) {
            if (now.isBefore(ghshTime)) {
                priceValueOrg.setIsSupply(SupplyEnum.NO.getKey());
            } else {
                priceValueOrg.setIsSupply(SupplyEnum.YES.getKey());
            }
        } else {
            ghshTime = supplyTimeActualMap.get(strCode);
            if (ghshTime != null) {
                if (now.isBefore(ghshTime)) {
                    priceValueOrg.setIsSupply(SupplyEnum.NO.getKey());
                } else {
                    priceValueOrg.setIsSupply(SupplyEnum.YES.getKey());
                }
            } else {
                priceValueOrg.setIsSupply(SupplyEnum.NO.getKey());
            }
        }

        String productCode = productOrg.getProductCode();
        if (isParkList.contains(productCode)) {
            priceValueOrg.setIsParking(IsDeleteEnum.YES.getKey());
            priceValueOrg.setParkingNum(buildItem.getRoomNum() == null ? 0 : buildItem.getRoomNum());
            parkingBuildList.add(buildItem.getBldPrdId());
        } else {
            priceValueOrg.setRoomNum(buildItem.getRoomNum() == null ? 0 : buildItem.getRoomNum());
            priceValueOrg.setIsParking(IsDeleteEnum.NO.getKey());
        }

        return priceValueOrg;
    }

    //寻找产品构成上级分类
    public Map<String, DictionaryCodeBO> getProductDictionary(List<MdmBuildAreaDetailBO> productItems) {
        Map<String, DictionaryCodeBO> dicMap = new HashMap<>();
        List<String> productCodes = Optional.of(productItems).orElseGet(ArrayList::new)
                .stream().map(MdmBuildAreaDetailBO::getProductCode)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(productCodes)) {
            List<DictionaryCodeBO> dicType = sysDictionaryService.selectByCodes(productCodes);
            if (CollectionUtils.isNotEmpty(dicType)) {
                for (DictionaryCodeBO bo : dicType) {
                    dicMap.put(bo.getChildCode(), bo);
                }
            }
        }
        return dicMap;
    }

    //创建投资版批次
    private PriceValueOrg createInvestmentBatchValueInfo(LocalDateTime now, String newVersionId, PriceValueOrg groupOrg, PanoplanBuildPlanItem batchItem){
        PriceValueOrg priceValueOrg = new PriceValueOrg();
        String batchId = UUIDUtils.create();
        priceValueOrg.setId(batchId);
        priceValueOrg.setVersionId(newVersionId);
        priceValueOrg.setPid(groupOrg.getId());
        priceValueOrg.setType(OrgTypeEunm.ORG_BATCH.getKey());
        priceValueOrg.setOrgId("");
        priceValueOrg.setOrgCode(batchItem.getBatchNum());
        priceValueOrg.setOrgName(NumberEnum.getValueByKey(batchItem.getBatchNum().trim())+"批次");
        priceValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
        priceValueOrg.setCreateTime(now);
        priceValueOrg.setUpdateTime(now);
        return priceValueOrg;
    }

    //创建投资版组团
    private PriceValueOrg createInvestmentGroupValueInfo(LocalDateTime now, String newVersionId, PriceValueOrg stageOrg, PanoplanBuildPlanItem groupItem) {
        PriceValueOrg priceValueOrg = new PriceValueOrg();
        String groupId = UUIDUtils.create();
        priceValueOrg.setId(groupId);
        priceValueOrg.setVersionId(newVersionId);
        priceValueOrg.setPid(stageOrg.getId());
        priceValueOrg.setType(OrgTypeEunm.ORG_GROUP.getKey());
        priceValueOrg.setOrgId(groupItem.getBatchId());
        priceValueOrg.setOrgCode(groupItem.getBatchCode());
        priceValueOrg.setOrgName(groupItem.getBatchName());
        priceValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
        priceValueOrg.setCreateTime(now);
        priceValueOrg.setUpdateTime(now);
        return priceValueOrg;
    }

    //创建组团
    public PriceValueOrg createGroupValueInfo(LocalDateTime now, String newVersionId, PriceValueOrg stageOrg, MdmBuildAreaDetailBO groupItem) {
        PriceValueOrg priceValueOrg = new PriceValueOrg();
        String groupId = UUIDUtils.create();
        priceValueOrg.setId(groupId);
        priceValueOrg.setVersionId(newVersionId);
        priceValueOrg.setPid(stageOrg.getId());
        priceValueOrg.setType(OrgTypeEunm.ORG_GROUP.getKey());
        priceValueOrg.setOrgId(groupItem.getGroupId());
        priceValueOrg.setOrgCode(groupItem.getGroupCode());
        priceValueOrg.setOrgName(groupItem.getGroupName());
        priceValueOrg.setIsParkingGroup(groupItem.getIsParkingGroup());
        priceValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
        priceValueOrg.setCreateTime(now);
        priceValueOrg.setUpdateTime(now);
        return priceValueOrg;
    }

    //创建分期
    public PriceValueOrg createStageValueInfo(LocalDateTime now, MdmStage mdmStage, String newVersionId) {
        PriceValueOrg projectOrg = new PriceValueOrg();
        projectOrg.setId( UUIDUtils.create());
        projectOrg.setVersionId(newVersionId);
        projectOrg.setPid("0");
        projectOrg.setType(OrgTypeEunm.ORG_STAGE.getKey());
        projectOrg.setOrgId(mdmStage.getProjectFid());
        projectOrg.setOrgCode(mdmStage.getStageCode());
        projectOrg.setOrgName(mdmStage.getStageName());
        projectOrg.setIsDelete(IsDeleteEnum.NO.getKey());
        projectOrg.setCreateTime(now);
        projectOrg.setUpdateTime(now);
        return projectOrg;
    }

    //主数据和楼栋计划楼栋匹配规则
    public void mdmToPanoBuildVerification(PanoPlanCastDecisionBO panoPlanCastDecisionBO, MdmBuildAreaBO mdmProductWarPlanBO, Map<String, String> panoplanBuildPlanItemMap, Map<String, PanoplanBuildPlanItem> panoplanItemMap) {
        if (panoPlanCastDecisionBO.getBuildItems().size() == mdmProductWarPlanBO.getBuildItems().size()) {
            List<String> buildList = new ArrayList<String>();
            for (PanoplanBuildPlanItem buildItem : panoPlanCastDecisionBO.getBuildItems()) {
                buildList.add(buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId());
                panoplanBuildPlanItemMap.put(buildItem.getId(), buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId());
                panoplanItemMap.put(buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId(), buildItem);
            }
            for (MdmBuildAreaDetailBO buildAreaBO : mdmProductWarPlanBO.getBuildItems()) {
                String itemKey = buildAreaBO.getGroupId() + "&" + buildAreaBO.getProductCode() + "&" + buildAreaBO.getBldPrdId();
                if (buildList.contains(itemKey)) {
                    PanoplanBuildPlanItem panoplanBuildPlanItem = panoplanItemMap.get(itemKey);
                    if(!panoplanBuildPlanItem.getSaleNum().equals(buildAreaBO.getBusinessType())){
                        throw new MsgException(CodeEnum.NON_SALABLE_ERROR);
                    }
                    if (buildAreaBO.getBusinessType().equals(SalyTypeEnum.SALABLE.getKey())
                            || buildAreaBO.getBusinessType().equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey())) {
                        BigDecimal totalSaleArea = buildAreaBO.getTotalSaleArea() == null ? new BigDecimal(0) : buildAreaBO.getTotalSaleArea();
                        if (totalSaleArea.compareTo(new BigDecimal(0)) <= 0) {
                            if (!isParkList.contains(buildAreaBO.getProductCode())) {
                                String message = "楼栋信息不完整:" + buildAreaBO.getFormatBuildingName() + "面积小于等于0";
                                CodeEnum.NON_PANOPLAN_BUILD.setMessage(message);
                                throw new MsgException(CodeEnum.NON_PANOPLAN_BUILD);
                            }
                        }

                        Integer roomNum = buildAreaBO.getRoomNum() == null ? 0 : buildAreaBO.getRoomNum();
                        if (roomNum <= 0) {
                            String message = "楼栋信息不完整:" + buildAreaBO.getFormatBuildingName() + "套数/个数小于等于0";
                            CodeEnum.NON_PANOPLAN_BUILD.setMessage(message);
                            throw new MsgException(CodeEnum.NON_PANOPLAN_BUILD);
                        }
                    }
                    buildList.remove(buildAreaBO.getGroupId() + "&" + buildAreaBO.getProductCode() + "&" + buildAreaBO.getBldPrdId());
                } else {
                    throw new MsgException(CodeEnum.NON_MATCH_VERSIONS);
                }
            }
            if (CollectionUtils.isNotEmpty(buildList)) {
                throw new MsgException(CodeEnum.NON_MATCH_VERSIONS);
            }
        } else {
            throw new MsgException(CodeEnum.NON_ORG_VERSIONS);
        }
    }

    //主数据和楼栋计划产品构成匹配规则
    public void mdmToPanoProductVerification(PanoPlanCastDecisionBO panoPlanCastDecisionBO, MdmBuildAreaBO mdmProductWarPlanBO) {
        if (panoPlanCastDecisionBO.getProductItems().size() == mdmProductWarPlanBO.getProductItems().size()) {
            List<String> productList = new ArrayList<String>();
            for (PanoplanBuildPlanItem productItem : panoPlanCastDecisionBO.getProductItems()) {
                productList.add(productItem.getBatchCode() + "&" + productItem.getProductTypeNum());
            }
            for (MdmBuildAreaDetailBO buildAreaBO : mdmProductWarPlanBO.getProductItems()) {
                if (!productList.contains(buildAreaBO.getGroupCode() + "&" + buildAreaBO.getProductCode())) {
                    throw new MsgException(CodeEnum.NON_ORG_VERSIONS);
                } else {
                    productList.remove(buildAreaBO.getGroupCode() + "&" + buildAreaBO.getProductCode());
                }
            }
            if (CollectionUtils.isNotEmpty(productList)) {
                throw new MsgException(CodeEnum.NON_ORG_VERSIONS);
            }
        } else {
            throw new MsgException(CodeEnum.NON_ORG_VERSIONS);
        }
    }

    //主数据和楼栋计划组团匹配规则
    public void mdmToPanoGroupVerification(PanoPlanCastDecisionBO panoPlanCastDecisionBO, MdmBuildAreaBO mdmProductWarPlanBO) {
        if (panoPlanCastDecisionBO.getGroupItems().size() == mdmProductWarPlanBO.getGroupItems().size()) {
            List<String> groupMap = Optional.of(panoPlanCastDecisionBO.getGroupItems()).orElseGet(ArrayList::new)
                    .stream().map(PanoplanBuildPlanItem::getBatchCode)
                    .collect(Collectors.toList());
            for (MdmBuildAreaDetailBO buildAreaBO : mdmProductWarPlanBO.getGroupItems()) {
                String groupCode = buildAreaBO.getGroupCode();
                if (!groupMap.contains(groupCode)) {
                    throw new MsgException(CodeEnum.NON_ORG_VERSIONS);
                } else {
                    groupMap.remove(groupCode);
                }
            }
            if (CollectionUtils.isNotEmpty(groupMap)) {
                throw new MsgException(CodeEnum.NON_ORG_VERSIONS);
            }
        } else {
            throw new MsgException(CodeEnum.NON_ORG_VERSIONS);
        }
    }

    //战规后货值版本创建规则验证
    private void strategyCreateVersionVerification(String projectFid, String versionType, String createVersionType, List<String> stageIds, Integer lable, Integer removeNoticeRule, MdmStage mdmStage, String instId, Integer type) {
        //项目下存在待提交审批、审批中、审批被驳回的版本，不允许新建版本
        if(!createVersionType.equals(VersionCreateEnum.AUTOMATICCREATE.getKey())){
            List<PriceVersion> approvalStates = priceVersionMapper.selectApprovalStateByStagesIds(stageIds, Arrays.asList(VersionStatusEnum.EXAMINEDAPPROVED.getKey(), VersionStatusEnum.APPROVED.getKey(), VersionStatusEnum.FAILUREAPPROVED.getKey()), IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isNotEmpty(approvalStates)){
                throw new MsgException(CodeEnum.EXIST_APPROVAL_PROJECT_VERSIONS);
            }
        }

        //分期存在待编制、编制中、待提交审批、审批中、审批已驳回的投资版价格版本，不允许新建该分期投资版价格版本
        List<String> existVersionTypes = Arrays.asList(VersionTypeEunm.INVESTMENT.getKey(),VersionTypeEunm.WARPLAN.getKey(),VersionTypeEunm.GETPRICE.getKey(),VersionTypeEunm.DYNAMIC.getKey());
        List<String> existVersionStates =  Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(),
                VersionStatusEnum.ORGANIZATION.getKey(), VersionStatusEnum.EXAMINEDAPPROVED.getKey(),
                VersionStatusEnum.APPROVED.getKey(),VersionStatusEnum.FAILUREAPPROVED.getKey() );
        List<PriceVersion> priceExistWPVersions = priceVersionService.selectApprovalVersionByFidAndTypesAndStates(projectFid, existVersionTypes, existVersionStates, IsDeleteEnum.NO.getKey());
        if(CollectionUtils.isNotEmpty(priceExistWPVersions)){
            throw new MsgException(CodeEnum.EXIST_APPROVAL_CASTDECISION_VERSIONS);
        }

        if(removeNoticeRule == null || !removeNoticeRule.equals(IsDeleteEnum.YES.getKey())){
            //系统创建版本如果有手动待办任务则不能创建
            if (createVersionType.equals(VersionCreateEnum.AUTOMATICCREATE.getKey())){
                List<SysNotice> notices = sysNoticeService.selectNoticeByProcessMode(projectFid, ModuleTypeEunm.PRICE.getKey(), VersionTypeEunm.DYNAMIC.getKey(), ProcessingStateEnum.UNTREATED.getKey(), IsDeleteEnum.NO.getKey());
                if (CollectionUtils.isNotEmpty(notices)){
                    throw new MsgException(CodeEnum.SYS_NOTICE_NON_EXCEPTION);
                }
            }
        }
        
        //货值创建普调版本
        if(type != null && type.intValue() == 1) {
        	//存在货值待办不允许创建
        	List<SysNotice> notices = sysNoticeService.selectNoticeByProjectFidAndTaskType(projectFid, Arrays.asList(VersionTypeEunm.WARPLAN.getKey(), VersionTypeEunm.DYNAMIC.getKey()), ModuleTypeEunm.PRICE.getKey(), ProcessingStateEnum.UNTREATED.getKey(), IsDeleteEnum.NO.getKey());
             if (CollectionUtils.isNotEmpty(notices)){
                 throw new MsgException(CodeEnum.EXIST_NOTICE_NON_EXCEPTION);
             }
        }

        //分期战规版货值已存在审批通过的大定价版货值版本时不允许新建该分期战规版货值版本
        if (versionType.equals(VersionTypeEunm.WARPLAN.getKey())){

            //异常创建版本去掉此验证
            if (!createVersionType.equals(VersionCreateEnum.EXCEPTIONCREATE.getKey())){
                //查询分期下是否有战规版本信息
                List<String> wpVersionStates = Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(),VersionStatusEnum.ORGANIZATION.getKey(),VersionStatusEnum.EXAMINEDAPPROVED.getKey(),VersionStatusEnum.APPROVED.getKey(),VersionStatusEnum.FAILUREAPPROVED.getKey(),VersionStatusEnum.SUCCESSAPPROVED.getKey());
                List<PriceVersion> priceWPVersions = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(projectFid, Arrays.asList(VersionTypeEunm.WARPLAN.getKey()), wpVersionStates, IsDeleteEnum.NO.getKey());
                if (CollectionUtils.isNotEmpty(priceWPVersions)){

                    //查询分期下是否有大定价版本信息
                    List<PriceVersion> warPlanVersionList = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(projectFid, Arrays.asList(VersionTypeEunm.GETPRICE.getKey()), Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
                    if (CollectionUtils.isNotEmpty(warPlanVersionList)){
                        throw new MsgException(CodeEnum.NON_EXISTENT_WP_VERSIONS);
                    }
                }
            }
        }

        //分期不存在审批通过战规版货值版本时不允许新建大定价版货值版本
        if (versionType.equals(VersionTypeEunm.GETPRICE.getKey())){
            List<PriceVersion> priceWPVersions = priceVersionMapper.selectApprovalVersionByFidAndTypesAndStates(projectFid, Arrays.asList(VersionTypeEunm.WARPLAN.getKey()), Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey()), IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isEmpty(priceWPVersions)){
                throw new MsgException(CodeEnum.NON_EXISTENT_GP_VERSIONS);
            }
        }

        //项目是否锁定，如果锁定，则不能创建货值版本
        if(!createVersionType.equals(VersionCreateEnum.AUTOMATICCREATE.getKey())) {
        	 boolean lockByProjectId = projectLockRecordService.isLockByProjectId(mdmStage.getProjectId());
             if(lockByProjectId){
                 throw new MsgException(CodeEnum.PROJECTID_TO_LOCK);
             }
        }
    }

    public List<PriceValueOrg> areaPartCollectInfo(LocalDateTime now, Map<String, List<PriceValueOrg>> preHouseMap, String newVersionId, Map<String, Map<String, PriceValueOrg>> houseOrgMap, List<PriceValueOrg> buildInsertList, List<PriceValueOrg> hoseSoleList, PriceValueOrg buildOrg, String buildId, String buildOrgId, Integer buildNum, BigDecimal buildArea, PriceValueOrg oldBuildOrg, Map<String, Integer> numMap, Map<String, BigDecimal> areaMap) {
        //可售面积段
        Integer sumSoleNum = 0;
        BigDecimal sumSolePrice = new BigDecimal(0);
        BigDecimal sumSoleArea = new BigDecimal(0);

        //已定价未售面积段
        Integer sumNotSaleNum = 0;
        BigDecimal sumNotSaleArea = new BigDecimal(0);
        BigDecimal sumNotSalePrice = new BigDecimal(0);

        //面积总数段信息
        BigDecimal roomTotalArea = new BigDecimal(0);
        Integer roomTotalNum = 0;

        //面积段总可售信息
        BigDecimal roomTotalSaleArea = new BigDecimal(0);
        Integer roomTotalSaleNum = 0;
        BigDecimal roomTotalSalePrice = new BigDecimal(0);

        //面积段自持汇总货值
        Integer roomNumZc = 0;
        BigDecimal roomAreaZc = new BigDecimal(0);
        BigDecimal roomPriceZc = new BigDecimal(0);

        //查看归集面积、套数和楼栋的面积、套数是否全部归集
        boolean isEntire = false;
        Integer subBuildNum = 0;
        BigDecimal subBuildArea = new BigDecimal(0);
        Integer collectBuildNum = numMap.get(buildOrgId)==null?0:numMap.get(buildOrgId);
        BigDecimal collectBuildArea = areaMap.get(buildOrgId)==null?new BigDecimal(0):areaMap.get(buildOrgId);
        if((collectBuildNum - buildNum) >= 0 || collectBuildArea.compareTo(buildArea) >= 0){
            isEntire = true;
            subBuildNum = buildNum - collectBuildNum;
            subBuildArea = priceVersionServiceImpl.BigDecimalSUB(buildArea, collectBuildArea);
        }else if((collectBuildNum - buildNum) < 0 && collectBuildArea.compareTo(buildArea) < 0){
            subBuildNum = buildNum - collectBuildNum;
            subBuildArea = priceVersionServiceImpl.BigDecimalSUB(buildArea, collectBuildArea);
        }

        //均价是否为空，不为空先计算下货值
        if(buildOrg.getAveragePriceHouse() != null && buildOrg.getAveragePriceHouse().compareTo(new BigDecimal(0)) > 0){
            buildOrg.setHouseCommodityValue(BigDecimalMUL(buildOrg.getSaleArea(), buildOrg.getAveragePriceHouse()));
        }

        //查看上版本数据信息
        Map<String, PriceValueOrg> preAreaPartHouseMap = new HashMap<String, PriceValueOrg>();
        List<PriceValueOrg> oldHouseOrgList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> preHouseOrgList = preHouseMap.get(buildOrgId);
        if(CollectionUtils.isNotEmpty(preHouseOrgList)){
            for (PriceValueOrg preHouseOrg : preHouseOrgList){
                String areaPart = preHouseOrg.getAreaPart();
                preAreaPartHouseMap.put(areaPart, preHouseOrg);
            }
        }

        //归集收集房源包
        List<PriceValueOrg> houseList = new ArrayList<PriceValueOrg>();
        List<String> roomAreaPartList = new ArrayList<String>();
        Map<String, PriceValueOrg> roomPriceValueOrgMap = houseOrgMap.get(buildOrgId);

        if(CollectionUtils.isNotEmpty(roomPriceValueOrgMap)){

            //去除只有自持的面积段
            Map<String, PriceValueOrg> roomPriceValueOrgCopyMap =new HashMap<String, PriceValueOrg>();
            for(Map.Entry<String, PriceValueOrg> roomHouses : roomPriceValueOrgMap.entrySet()){
                PriceValueOrg org = roomHouses.getValue();
                Integer totalNum = org.getTotalNum()==null?0:org.getTotalNum();
                BigDecimal totalSaleArea = org.getTotalSaleArea()==null?new BigDecimal(0):org.getTotalSaleArea();

                Integer orgRoomZc = org.getRoomZc()==null?0:org.getRoomZc();
                BigDecimal orgAreaZc = org.getAreaZc()==null?new BigDecimal(0):org.getAreaZc();
                BigDecimal orgPriceRoomZc = org.getPriceRoomZc();

                if(totalNum.equals(orgRoomZc) && totalSaleArea.compareTo(orgAreaZc) == 0){
                    org.setIsDelete(IsDeleteEnum.YES.getKey());
                    houseList.add(org);

                    roomTotalNum = roomTotalNum + orgRoomZc;
                    roomTotalArea = BigDecimalADD(roomTotalArea, orgAreaZc);

                    roomNumZc = orgRoomZc;
                    roomAreaZc = orgAreaZc;
                    roomPriceZc = orgPriceRoomZc;
                }else{
                    roomPriceValueOrgCopyMap.put(roomHouses.getKey(), roomHouses.getValue());
                }
            }

            roomPriceValueOrgMap.clear();
            roomPriceValueOrgMap.putAll(roomPriceValueOrgCopyMap);

            //排序
            roomPriceValueOrgMap = sortMapByKey(roomPriceValueOrgMap);

            for (Map.Entry<String, PriceValueOrg> roomHouses : roomPriceValueOrgMap.entrySet()){
                PriceValueOrg roomValueOrg = roomHouses.getValue();
                roomValueOrg.setPid(buildId);
                roomValueOrg.setVersionId(buildOrg.getVersionId());
                roomValueOrg.setUpdateTime(now);

                //部分归集
                if(!isEntire){
                    PriceValueOrg preOrg = preAreaPartHouseMap.get(roomValueOrg.getAreaPart());
                    if(preOrg != null){

                        //需要保存的信息
                        Integer bcNum = 0;
                        BigDecimal bcArea = new BigDecimal(0);
                        BigDecimal bcAveragePrice = new BigDecimal(0);
                        BigDecimal bcHousePrice = new BigDecimal(0);

                        //上一版面积段信息
                        Integer preRoomNum = preOrg.getRoomNum()==null?0:preOrg.getRoomNum();
                        BigDecimal preSaleArea = preOrg.getSaleArea()==null?new BigDecimal(0):preOrg.getSaleArea();
                        BigDecimal preAveragePriceHouse = preOrg.getAveragePriceHouse()==null?new BigDecimal(0):preOrg.getAveragePriceHouse();

                        //归集面积段信息
                        Integer roomRoomNum = roomValueOrg.getRoomNum()==null?0:roomValueOrg.getRoomNum();
                        BigDecimal roomSaleArea = roomValueOrg.getSaleArea()==null?new BigDecimal(0):roomValueOrg.getSaleArea();
                        BigDecimal roomCommValue = roomValueOrg.getHouseCommodityValue()==null?new BigDecimal(0):roomValueOrg.getHouseCommodityValue();

                        roomRoomNum = roomRoomNum + (roomValueOrg.getRoomZc()==null?0:roomValueOrg.getRoomZc());
                        roomSaleArea = BigDecimalADD(roomSaleArea, roomValueOrg.getAreaZc());

                        //剩余归集面积和套数
                        Integer subNum = subBuildNum - roomRoomNum;
                        BigDecimal subArea = priceVersionServiceImpl.BigDecimalSUB(subBuildArea, roomSaleArea);
                        if (subNum > 0 && subArea.compareTo(new BigDecimal(0)) > 0){

                            //多余拆分的面积和套数
                            Integer sfNum = preRoomNum - roomRoomNum;
                            BigDecimal sfArea = priceVersionServiceImpl.BigDecimalSUB(preSaleArea, roomSaleArea);

                            //剩余的拆分的面积和套数
                            Integer sfSubNum = subBuildNum - sfNum;
                            BigDecimal sfSubArea = priceVersionServiceImpl.BigDecimalSUB(subBuildArea, sfArea);

                            if(sfSubNum > 0 && sfSubArea.compareTo(new BigDecimal(0)) > 0){
                                if(preRoomNum > roomRoomNum && preSaleArea.compareTo(roomSaleArea) > 0){
                                    bcNum = preRoomNum;
                                    bcArea = preSaleArea;
                                }else {
                                    bcNum = roomValueOrg.getRoomNum();
                                    bcArea = roomValueOrg.getSaleArea();
                                }

                                if(roomRoomNum >= preRoomNum || roomSaleArea.compareTo(preSaleArea) >= 0){
                                    bcAveragePrice = roomValueOrg.getAveragePriceHouse();

                                    bcHousePrice = BigDecimalMUL(bcAveragePrice, bcArea);
                                }else{
                                    //已有面积段面积 - SUM(已定价房间面积)
                                    BigDecimal areaSubArea = priceVersionServiceImpl.BigDecimalSUB(preSaleArea, roomSaleArea);

                                    //已定价货值 + 剩余面积段货值
                                    BigDecimal areaSubPrice = BigDecimalMUL(areaSubArea, preAveragePriceHouse);

                                    bcHousePrice = BigDecimalADD(areaSubPrice, roomCommValue);
                                    bcAveragePrice = bigDecimalDIV(bcHousePrice, bcArea);
                                }

                                subBuildNum = sfSubNum;
                                subBuildArea = sfSubArea;
                            }else{
                                if (sfSubNum < 0 && sfSubArea.compareTo(new BigDecimal(0)) < 0){

                                    //保货值逻辑
                                    //面积段新金额 = (上一版面积段总货值 - 上一版面积段归集的货值)
                                    //  / (上一版面积段总面积 - 上一版面积段归集的面积) * (上一版面积段面积 - 新归集面积段的面积)
                                    //  + 新归集面积段的金额
                                    //面积段新均价 = 面积段新的金额 / 面积段面积
                                    BigDecimal preCollectPrice = BigDecimalADD(preOrg.getPriceSold(), preOrg.getPricePriced());
                                    BigDecimal subPrePrice = priceVersionServiceImpl.BigDecimalSUB(preOrg.getHouseCommodityValue(), preCollectPrice);

                                    BigDecimal preCollectArea = BigDecimalADD(preOrg.getAreaSold(), preOrg.getAreaPriced());
                                    BigDecimal subPreArea = priceVersionServiceImpl.BigDecimalSUB(preOrg.getSaleArea(), preCollectArea);

                                    BigDecimal roomCollectArea = BigDecimalADD(roomValueOrg.getAreaSold(), roomValueOrg.getAreaPriced());
                                    BigDecimal subRoomArea = priceVersionServiceImpl.BigDecimalSUB(preOrg.getSaleArea(), roomCollectArea);

                                    BigDecimal roomCollectPrice = BigDecimalADD(roomValueOrg.getPriceSold(), roomValueOrg.getPricePriced());

                                    bcNum = subBuildNum + roomRoomNum;
                                    bcArea = BigDecimalADD(subBuildArea, roomSaleArea);
                                    bcHousePrice = BigDecimalADD(BigDecimalMUL(bigDecimalDIV(subPrePrice, subPreArea), subRoomArea), roomCollectPrice) ;
                                    bcAveragePrice = bigDecimalDIV(bcHousePrice, roomValueOrg.getSaleArea());
                                }else if (sfSubNum >= 0 && sfSubArea.compareTo(new BigDecimal(0)) < 0){

                                    bcNum = sfNum + roomRoomNum + sfSubNum;
                                    bcArea = BigDecimalADD(subBuildArea, roomSaleArea);
                                    bcAveragePrice = roomValueOrg.getAveragePriceHouse();
                                    bcHousePrice = BigDecimalMUL(bcAveragePrice, bcArea);
                                }else if (sfSubNum < 0 && sfSubArea.compareTo(new BigDecimal(0)) >= 0){

                                    bcNum = subBuildNum + roomRoomNum;
                                    bcArea = BigDecimalADD(BigDecimalADD(sfArea, roomSaleArea), sfSubArea);
                                    bcAveragePrice = roomValueOrg.getAveragePriceHouse();
                                    bcHousePrice = BigDecimalMUL(bcAveragePrice, bcArea);
                                }else{

                                    bcNum = roomValueOrg.getRoomNum();
                                    bcArea = roomValueOrg.getSaleArea();
                                    bcAveragePrice = roomValueOrg.getAveragePriceHouse();
                                    bcHousePrice = BigDecimalMUL(bcAveragePrice, bcArea);
                                }

                                subBuildNum = 0;
                                subBuildArea = new BigDecimal(0);
                            }
                        }else{
                            bcNum = roomRoomNum;
                            bcArea = roomSaleArea;

                            bcAveragePrice = roomValueOrg.getAveragePriceHouse();
                            bcHousePrice = BigDecimalMUL(bcAveragePrice, bcArea);
                        }

                        roomValueOrg.setHouseCommodityValue(bcHousePrice);
                        roomValueOrg.setRoomNum(bcNum);
                        roomValueOrg.setNum(bcNum);
                        roomValueOrg.setSaleArea(bcArea);
                        roomValueOrg.setAveragePriceHouse(bcAveragePrice);
                    }
                }

                houseList.add(roomValueOrg);
                roomAreaPartList.add(roomValueOrg.getAreaPart());

                roomTotalArea = BigDecimalADD(roomTotalArea, roomValueOrg.getSaleArea());
                roomTotalArea = BigDecimalADD(roomTotalArea, roomValueOrg.getAreaZc());
                roomTotalNum = roomTotalNum + (roomValueOrg.getRoomNum()==null?0:roomValueOrg.getRoomNum());
                roomTotalNum = roomTotalNum + (roomValueOrg.getRoomZc()==null?0:roomValueOrg.getRoomZc());

                roomTotalSaleArea = BigDecimalADD(roomTotalSaleArea, roomValueOrg.getSaleArea());
                roomTotalSaleNum = roomTotalSaleNum + (roomValueOrg.getRoomNum()==null?0:roomValueOrg.getRoomNum());
                roomTotalSalePrice = BigDecimalADD(roomTotalSalePrice, roomValueOrg.getHouseCommodityValue());

                sumSolePrice = BigDecimalADD(sumSolePrice, roomValueOrg.getPriceSold());
                sumSoleArea = BigDecimalADD(sumSoleArea, roomValueOrg.getAreaSold());
                sumSoleNum = sumSoleNum + (roomValueOrg.getRoomSold()==null?0:roomValueOrg.getRoomSold());

                sumNotSaleNum = sumNotSaleNum + (roomValueOrg.getRoomPriced()==null?0:roomValueOrg.getRoomPriced());
                sumNotSaleArea = BigDecimalADD(sumNotSaleArea, roomValueOrg.getAreaPriced());
                sumNotSalePrice = BigDecimalADD(sumNotSalePrice, roomValueOrg.getPricePriced());

                roomNumZc = roomNumZc + (roomValueOrg.getRoomZc()==null?0:roomValueOrg.getRoomZc());
                roomAreaZc = BigDecimalADD(roomAreaZc, roomValueOrg.getAreaZc());
                roomPriceZc = BigDecimalADD(roomPriceZc, roomValueOrg.getPriceRoomZc());
            }
        }

        //排序
        if (CollectionUtils.isNotEmpty(houseList)){
            houseAscSortList(houseList);
        }

        //判断面积
        BigDecimal surplusArea = priceVersionServiceImpl.BigDecimalSUB(roomTotalArea, buildArea);

        //判断套数
        int surplusNum = roomTotalNum - buildNum;

        if(surplusArea.compareTo(new BigDecimal(0)) < 0 && surplusNum < 0){

            //上一版面积段数据
            if(CollectionUtils.isNotEmpty(preHouseOrgList)){
                for (PriceValueOrg preHouseOrg : preHouseOrgList){
                    String areaPart = preHouseOrg.getAreaPart();
                    if (!roomAreaPartList.contains(areaPart)){
                        preHouseOrg.setIsSplit(IsSplitEnum.YES.getKey());
                        oldHouseOrgList.add(preHouseOrg);
                    }
                }
            }

            //排序
            if (CollectionUtils.isNotEmpty(oldHouseOrgList)){
                houseDescSortList(oldHouseOrgList);
            }

            //面积段规则处理
            int subNum = buildNum - roomTotalNum;
            BigDecimal subArea = priceVersionServiceImpl.BigDecimalSUB(buildArea, roomTotalArea);
            if(CollectionUtils.isNotEmpty(oldHouseOrgList)){
                bo : for (PriceValueOrg oldOrg : oldHouseOrgList){
                    if(subNum == 0 || subArea.compareTo(new BigDecimal(0)) == 0){
                        continue bo;
                    }

                    int bcNum = subNum - (oldOrg.getRoomNum()==null?0:oldOrg.getRoomNum());
                    BigDecimal bcArea = priceVersionServiceImpl.BigDecimalSUB(subArea, oldOrg.getSaleArea());
                    if(bcNum > 0 && bcArea.compareTo(new BigDecimal(0)) > 0){
                        subNum = bcNum;
                        subArea = bcArea;

                        bcNum = oldOrg.getRoomNum()==null?0:oldOrg.getRoomNum();
                        bcArea = oldOrg.getSaleArea()==null?new BigDecimal(0):oldOrg.getSaleArea();
                    }else{
                        bcNum = subNum;
                        bcArea = subArea;

                        subNum = 0;
                        subArea = new BigDecimal(0);
                    }

                    PriceValueOrg houseOrg = new PriceValueOrg();
                    BeanUtils.copyProperties(oldOrg, houseOrg);
                    houseOrg.setId(UUIDUtils.create());
                    houseOrg.setPid(buildId);
                    houseOrg.setVersionId(buildOrg.getVersionId());
                    houseOrg.setIsSplit(IsSplitEnum.YES.getKey());
                    houseOrg.setNum(bcNum);
                    houseOrg.setRoomNum(bcNum);
                    houseOrg.setSaleArea(bcArea);
                    houseOrg.setHouseCommodityValue(BigDecimalMUL(bcArea, houseOrg.getAveragePriceHouse()));
                    houseOrg.setRoomSold(0);
                    houseOrg.setAreaSold(new BigDecimal(0));
                    houseOrg.setPriceSold(new BigDecimal(0));
                    houseOrg.setRoomPriced(0);
                    houseOrg.setAreaPriced(new BigDecimal(0));
                    houseOrg.setPricePriced(new BigDecimal(0));
                    houseOrg.setTotalNum(bcNum);
                    houseOrg.setTotalSaleArea(bcArea);
                    houseOrg.setCreateTime(now);
                    houseOrg.setUpdateTime(now);
                    houseOrg.setIsSplit(IsSplitEnum.YES.getKey());

                    houseList.add(houseOrg);

                    roomTotalSaleArea = BigDecimalADD(roomTotalSaleArea, houseOrg.getSaleArea());
                    roomTotalSaleNum = roomTotalSaleNum + (houseOrg.getRoomNum()==null?0:houseOrg.getRoomNum());
                    roomTotalSalePrice = BigDecimalADD(roomTotalSalePrice, houseOrg.getHouseCommodityValue());

                    roomTotalArea = BigDecimalADD(roomTotalArea, houseOrg.getSaleArea());
                    roomTotalNum = roomTotalNum + (houseOrg.getRoomNum()==null?0:houseOrg.getRoomNum());
                }
            }

            houseAscSortList(houseList);
            if (subNum > 0 && subArea.compareTo(new BigDecimal(0)) > 0){
                roomTotalArea = BigDecimalADD(roomTotalArea, subArea);
                roomTotalNum = roomTotalNum + subNum;

                //判断是否有上一版数据
                if (CollectionUtils.isNotEmpty(preHouseOrgList)){
                    PriceValueOrg valueOrg = houseList.get(0);
                    if (valueOrg != null){
                        BigDecimal oldHouseCommodityValue = valueOrg.getHouseCommodityValue();

                        valueOrg.setNum(subNum+valueOrg.getNum());
                        valueOrg.setRoomNum(subNum+valueOrg.getRoomNum());
                        valueOrg.setSaleArea(BigDecimalADD(subArea, valueOrg.getSaleArea()));
                        valueOrg.setHouseCommodityValue(BigDecimalMUL(valueOrg.getSaleArea(), valueOrg.getAveragePriceHouse()));

                        houseList.remove(0);
                        houseList.add(0, valueOrg);

                        roomTotalSaleArea = BigDecimalADD(roomTotalSaleArea, subArea);
                        roomTotalSaleNum = roomTotalSaleNum + subNum;

                        roomTotalSalePrice = priceVersionServiceImpl.BigDecimalSUB(roomTotalSalePrice, oldHouseCommodityValue);
                        roomTotalSalePrice = BigDecimalADD(roomTotalSalePrice, valueOrg.getHouseCommodityValue());
                    }
                }else{
                    if(CollectionUtils.isNotEmpty(houseList)){
                        PriceValueOrg valueOrg = houseList.get(0);

                        BigDecimal oldHouseCommodityValue = valueOrg.getHouseCommodityValue();
                        String orgName = valueOrg.getOrgName();
                        if (orgName.equals(Constants.ORTHER_HOUSE_NAME)){
                            valueOrg.setNum(valueOrg.getNum()+subNum);
                            valueOrg.setRoomNum(valueOrg.getNum()+subNum);
                            valueOrg.setSaleArea(BigDecimalADD(valueOrg.getSaleArea(), subArea));
                            valueOrg.setHouseCommodityValue(BigDecimalMUL(valueOrg.getSaleArea(), valueOrg.getAveragePriceHouse()));

                            houseList.remove(0);
                            houseList.add(0, valueOrg);

                            roomTotalSaleArea = BigDecimalADD(roomTotalSaleArea, subArea);
                            roomTotalSaleNum = roomTotalSaleNum + subNum;

                            roomTotalSalePrice = priceVersionServiceImpl.BigDecimalSUB(roomTotalSalePrice, oldHouseCommodityValue);
                            roomTotalSalePrice = BigDecimalADD(roomTotalSalePrice, valueOrg.getHouseCommodityValue());
                        }else{
                            BigDecimal oldHousePrice = new BigDecimal(0);
                            if(oldBuildOrg != null){
                                oldHousePrice = oldBuildOrg.getHouseCommodityValue();
                            }
                            BigDecimal otherHouseValue = priceVersionServiceImpl.BigDecimalSUB(oldHousePrice, roomTotalSalePrice);

                            //归集其他
                            PriceValueOrg otherOrg = new PriceValueOrg();
                            otherOrg.setId(UUIDUtils.create());
                            otherOrg.setPid(buildOrg.getId());
                            otherOrg.setVersionId(newVersionId);
                            otherOrg.setAreaPart(Constants.ORTHER_HOUSE_NAME);
                            otherOrg.setType(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey());
                            otherOrg.setOrgCode(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey());
                            otherOrg.setOrgName(Constants.ORTHER_HOUSE_NAME);
                            otherOrg.setSaleArea(subArea);
                            otherOrg.setNum(subNum);
                            otherOrg.setRoomNum(subNum);
                            otherOrg.setTotalNum(subNum);
                            otherOrg.setTotalSaleArea(subArea);

                            if (otherHouseValue.compareTo(new BigDecimal(0)) > 0){
                                otherOrg.setHouseCommodityValue(otherHouseValue);
                                otherOrg.setAveragePriceHouse(bigDecimalDIV(otherHouseValue, subArea));
                            }else{
                                BigDecimal bigDecimal = bigDecimalDIV(roomTotalSalePrice, roomTotalSaleArea);
                                otherOrg.setAveragePriceHouse(bigDecimal);
                                otherOrg.setHouseCommodityValue(BigDecimalMUL(bigDecimal, otherOrg.getSaleArea()));
                            }

                            otherOrg.setIsSplit(IsSplitEnum.YES.getKey());
                            otherOrg.setIsDelete(IsDeleteEnum.NO.getKey());
                            otherOrg.setCreateTime(now);
                            otherOrg.setUpdateTime(now);
                            houseList.add(otherOrg);

                            roomTotalSaleArea = BigDecimalADD(roomTotalSaleArea, otherOrg.getSaleArea());
                            roomTotalSaleNum = roomTotalSaleNum + (otherOrg.getRoomNum()==null?0:otherOrg.getRoomNum());
                            roomTotalSalePrice = BigDecimalADD(roomTotalSalePrice, otherOrg.getHouseCommodityValue());
                        }
                    }
                }
            }

            buildOrg.setPrice(roomTotalSalePrice);
            if (roomTotalSalePrice != null && roomTotalSalePrice.compareTo(new BigDecimal(0)) != 0){
                buildOrg.setHouseCommodityValue(roomTotalSalePrice);
                buildOrg.setAveragePriceHouse(bigDecimalDIV(roomTotalSalePrice, buildOrg.getSaleArea()));
            }else{
                buildOrg.setHouseCommodityValue(BigDecimalMUL(buildOrg.getSaleArea(), buildOrg.getAveragePriceHouse()));
            }

            if(roomTotalSaleNum != 0 && roomTotalSaleArea.compareTo(new BigDecimal(0)) != 0){
                buildOrg.setNum(roomTotalSaleNum);
                buildOrg.setRoomNum(roomTotalSaleNum);
                buildOrg.setSaleArea(roomTotalSaleArea);
            }else{
                buildOrg.setNum(roomTotalNum);
                buildOrg.setRoomNum(roomTotalNum);
                buildOrg.setSaleArea(roomTotalArea);
            }

            buildOrg.setRoomSold(sumSoleNum);
            buildOrg.setAreaSold(sumSoleArea);
            buildOrg.setPriceSold(sumSolePrice);
            buildOrg.setRoomPriced(sumNotSaleNum);
            buildOrg.setAreaPriced(sumNotSaleArea);
            buildOrg.setPricePriced(sumNotSalePrice);

            buildOrg.setTotalNum(roomTotalNum);
            buildOrg.setTotalSaleArea(roomTotalArea);
            buildOrg.setRoomZc(roomNumZc);
            buildOrg.setAreaZc(roomAreaZc);
            buildOrg.setPriceRoomZc(roomPriceZc);

            buildInsertList.add(buildOrg);
        }else{
            //从新计算楼栋的面积、套数、均价、金额(货值)
            buildOrg.setSaleArea(roomTotalSaleArea);
            buildOrg.setNum(roomTotalSaleNum);
            buildOrg.setRoomNum(roomTotalSaleNum);
            buildOrg.setAveragePriceHouse(bigDecimalDIV(roomTotalSalePrice, buildOrg.getSaleArea()));
            buildOrg.setPrice(roomTotalSalePrice);
            buildOrg.setHouseCommodityValue(roomTotalSalePrice);
            buildOrg.setRoomSold(sumSoleNum);
            buildOrg.setAreaSold(sumSoleArea);
            buildOrg.setPriceSold(sumSolePrice);
            buildOrg.setRoomPriced(sumNotSaleNum);
            buildOrg.setAreaPriced(sumNotSaleArea);
            buildOrg.setPricePriced(sumNotSalePrice);
            buildOrg.setTotalNum(roomTotalNum);
            buildOrg.setTotalSaleArea(roomTotalArea);
            buildOrg.setRoomZc(roomNumZc);
            buildOrg.setAreaZc(roomAreaZc);
            buildOrg.setPriceRoomZc(roomPriceZc);

            buildInsertList.add(buildOrg);
        }

        hoseSoleList.addAll(houseList);
        return hoseSoleList;
    }

    //面积段排序
    private void houseAscSortList(List<PriceValueOrg> hoseSoleList) {
        hoseSoleList.sort((a, b) -> {
            String aAreaPart = a.getAreaPart();
            String bAreaPart = b.getAreaPart();

            Integer aComStr = 0;
            Integer bComStr = 0;

            if (aAreaPart.equals(Constants.ORTHER_HOUSE_NAME)) {
                aComStr = -1;
            } else {
                String[] aAplitStr = aAreaPart.split("-");
                aComStr = Integer.valueOf(aAplitStr[0]);
            }

            if (bAreaPart.equals(Constants.ORTHER_HOUSE_NAME)) {
                bComStr = -1;
            } else {
                String[] bSplitStr = bAreaPart.split("-");
                bComStr = Integer.valueOf(bSplitStr[0]);
            }

            return aComStr.compareTo(bComStr);
        });
    }

    //面积段排序
    public static Map<String, PriceValueOrg> sortMapByKey(Map<String, PriceValueOrg> map) {
        if (map == null || map.isEmpty()) {
            return null;
        }
        Map<String, PriceValueOrg> sortMap = new TreeMap<String, PriceValueOrg>(new Comparator<String>() {

            @Override
            public int compare(String str1, String str2) {
                String aAreaPart = str1;
                String bAreaPart = str2;

                Integer aComStr = 0;
                Integer bComStr = 0;

                String[] aAplitStr = aAreaPart.split("-");
                aComStr = Integer.valueOf(aAplitStr[0]);

                String[] bSplitStr = bAreaPart.split("-");
                bComStr = Integer.valueOf(bSplitStr[0]);

                return bComStr.compareTo(aComStr);
            }
        });

        sortMap.putAll(map);
        return sortMap;
    }

    //层级累加信息
    public void valueUpSummary(PriceValueOrg upOrg, PriceValueOrg downOrg) {

        if (downOrg.getType().equals(OrgTypeEunm.ORG_BUILD.getKey()) || downOrg.getType().equals(OrgTypeEunm.ORG_PRODUCT.getKey())){
            if(StringUtils.isNotEmpty(downOrg.getBusinessType())){
                if(downOrg.getBusinessType().equals(SalyTypeEnum.RENTED.getKey()) ||
                        downOrg.getBusinessType().equals(SalyTypeEnum.NOT_RENTABLE.getKey())){
                    return;
                }
            }
        }

        logger.info("====== start =======");
        logger.info("##################  upOrg :"+(upOrg==null?"null": JSON.toJSON(upOrg)));
        logger.info("##################  downOrg :"+(downOrg==null?"null": JSON.toJSON(downOrg)));
        logger.info("====== end =======");

        if(upOrg != null && downOrg != null){
            BigDecimal commValue = BigDecimalADD(downOrg.getCommodityValue(), upOrg.getCommodityValue());
            BigDecimal houseValue = BigDecimalADD(downOrg.getHouseCommodityValue(), upOrg.getHouseCommodityValue());
            BigDecimal notCommValue = BigDecimalADD(downOrg.getNotCommodityValue(), upOrg.getNotCommodityValue());

            upOrg.setCommodityValue(commValue);
            upOrg.setHouseCommodityValue(houseValue);
            upOrg.setNotCommodityValue(notCommValue);

            upOrg.setNum((downOrg.getNum() == null ? 0 : downOrg.getNum()) + (upOrg.getNum() == null ? 0 : upOrg.getNum()));
            upOrg.setRoomNum((downOrg.getRoomNum() == null ? 0 : downOrg.getRoomNum()) + (upOrg.getRoomNum() == null ? 0 : upOrg.getRoomNum()));
            upOrg.setParkingNum((downOrg.getParkingNum() == null ? 0 : downOrg.getParkingNum()) + (upOrg.getParkingNum() == null ? 0 : upOrg.getParkingNum()));
            upOrg.setForsaleParkingNum((downOrg.getForsaleParkingNum() == null ? 0 : downOrg.getForsaleParkingNum()) + (upOrg.getForsaleParkingNum() == null ? 0 : upOrg.getForsaleParkingNum()));

            if(downOrg.getType().equals(OrgTypeEunm.ORG_BUILD.getKey())){
                if (downOrg.getIsParking().equals(IsDeleteEnum.NO.getKey())){
                    upOrg.setSaleArea(BigDecimalADD(downOrg.getSaleArea(), upOrg.getSaleArea()));
                }
            }else if (downOrg.getType().equals(OrgTypeEunm.ORG_SALE_PACKAGE.getKey())
                    || downOrg.getType().equals(OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey())
                    || downOrg.getType().equals(OrgTypeEunm.ORG_SALING_PARKING.getKey())
                    || downOrg.getType().equals(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())){

            }else{
                upOrg.setSaleArea(BigDecimalADD(downOrg.getSaleArea(), upOrg.getSaleArea()));
            }

            upOrg.setAveragePriceHouse(bigDecimalDIV(houseValue, upOrg.getSaleArea()));
            upOrg.setAveragePriceParking(bigDecimalDIV(notCommValue, new BigDecimal(upOrg.getParkingNum() == null ? 0 : upOrg.getParkingNum())));

            upOrg.setPriceSold(BigDecimalADD(downOrg.getPriceSold(), upOrg.getPriceSold()));
            upOrg.setAreaSold(BigDecimalADD(downOrg.getAreaSold(), upOrg.getAreaSold()));
            upOrg.setRoomSold((downOrg.getRoomSold() == null ? 0 : downOrg.getRoomSold()) + (upOrg.getRoomSold() == null ? 0 : upOrg.getRoomSold()));
            upOrg.setParkingSold((downOrg.getParkingSold() == null ? 0 : downOrg.getParkingSold()) + (upOrg.getParkingSold() == null ? 0 : upOrg.getParkingSold()));

            upOrg.setPricePriced(BigDecimalADD(downOrg.getPricePriced(), upOrg.getPricePriced()));
            upOrg.setAreaPriced(BigDecimalADD(downOrg.getAreaPriced(), upOrg.getAreaPriced()));
            upOrg.setRoomPriced((downOrg.getRoomPriced() == null ? 0 : downOrg.getRoomPriced()) + (upOrg.getRoomPriced() == null ? 0 : upOrg.getRoomPriced()));
            upOrg.setParkingPriced((downOrg.getParkingPriced() == null ? 0 : downOrg.getParkingPriced()) + (upOrg.getParkingPriced() == null ? 0 : upOrg.getParkingPriced()));

            //自持货值
            upOrg.setRoomZc((downOrg.getRoomZc() == null ? 0 : downOrg.getRoomZc()) + (upOrg.getRoomZc() == null ? 0 : upOrg.getRoomZc()));
            upOrg.setAreaZc(BigDecimalADD(downOrg.getAreaZc(), upOrg.getAreaZc()));
            upOrg.setPriceRoomZc(BigDecimalADD(downOrg.getPriceRoomZc(), upOrg.getPriceRoomZc()));
            upOrg.setParkingZc((downOrg.getParkingZc() == null ? 0 : downOrg.getParkingZc()) + (upOrg.getParkingPriced() == null ? 0 : upOrg.getParkingPriced()));
            upOrg.setPriceParkingZc(BigDecimalADD(downOrg.getPriceParkingZc(), upOrg.getPriceParkingZc()));

            upOrg.setTotalNum((downOrg.getTotalNum() == null ? 0 : downOrg.getTotalNum()) + (upOrg.getTotalNum() == null ? 0 : upOrg.getTotalNum()));
            upOrg.setTotalSaleArea(BigDecimalADD(downOrg.getTotalSaleArea(), upOrg.getTotalSaleArea()));
        }
    }

    /***
     * 归集NOS面积段
     * @param kingdeeProjectFid 金蝶分期id
     * @param now 时间
     * @param tradeDataList 签约集合
     */
    public Map<String, Map> nosCollectHouse(String kingdeeProjectFid, LocalDateTime now,List<NosTradedataDto>tradeDataList) {
        Map<String, Map> resultMap = new HashMap<>();

        Map<String, PriceValueOrg> soldParkingMap = new HashMap<String, PriceValueOrg>();//已售车位
        Map<String, Map<String, PriceValueOrg>> houseOrgMap = new HashMap<String, Map<String, PriceValueOrg>>();//已售面积段
        Map<String, BigDecimal> areaMap = new HashMap<>();//楼栋下面积段总面积
        Map<String, Integer> numMap = new HashMap<>();//楼栋下面积段总套数

        //查询面积段信息
        List<SysDictionary> codes = sysDictionaryService.selectDictionaryByType(Arrays.asList("area_segmenta"));

        //查询NOS补差
        Map<String, NOSRoomCompensationDto> comMap = new HashMap<String, NOSRoomCompensationDto>();
        List<NOSRoomCompensationDto> nosRoomCompensationDtos = dmOdsNosTradedataviewformarsService.selectTradeCompensation(kingdeeProjectFid);
        if(CollectionUtils.isNotEmpty(nosRoomCompensationDtos)){
            logger.info("#######################   nosCollectHouse   nosRoomCompensationDtos.size:"+nosRoomCompensationDtos.size());
            for (NOSRoomCompensationDto comp : nosRoomCompensationDtos){
                comMap.put(comp.getRoomId(), comp);
            }
        }

        //查询NOS签约信息
        List<NosTradedataDto> nosTradeDtos = dmOdsNosTradedataviewformarsService.selectTradeRooms(kingdeeProjectFid);
        Map<String, NosTradedataDto> nosTradedataMap = new HashMap<String, NosTradedataDto>();
        if(CollectionUtils.isNotEmpty(nosTradeDtos)){
            for(NosTradedataDto nosTradeDto : nosTradeDtos){
                NosTradedataDto nosTradedataDto = nosTradedataMap.get(nosTradeDto.getRoomId());
                if(nosTradedataDto != null){
                    nosTradedataDto.setTradeMoney(BigDecimalADD(nosTradeDto.getTradeMoney(),nosTradedataDto.getTradeMoney()));
                    nosTradedataDto.setRoomArea(BigDecimalADD(nosTradeDto.getRoomArea(),nosTradedataDto.getRoomArea()));
                    nosTradedataDto.setRoomCount(BigDecimalADD(nosTradeDto.getRoomCount(),nosTradedataDto.getRoomCount()));
                }else{
                    nosTradedataDto = nosTradeDto;
                }
                nosTradedataMap.put(nosTradeDto.getRoomId(), nosTradedataDto);
            }
        }
        //查询NOS退房信息
        List<NosTradedataDto> nosCheckDtos = dmOdsNosTradedataviewformarsService.selectCheckRooms(kingdeeProjectFid);
        if(CollectionUtils.isNotEmpty(nosCheckDtos)){
            for(NosTradedataDto nosCheckDto : nosCheckDtos){
                NosTradedataDto nosTradeDto = nosTradedataMap.get(nosCheckDto.getRoomId());
                if (nosTradeDto != null){
                    BigDecimal num = BigDecimalADD(nosTradeDto.getRoomCount(),nosCheckDto.getRoomCount());
                    if (num.compareTo(new BigDecimal(0)) <= 0){
                        nosTradedataMap.remove(nosCheckDto.getRoomId());
                    }else{
                        nosTradeDto.setTradeMoney(BigDecimalADD(nosTradeDto.getTradeMoney(),nosCheckDto.getTradeMoney()));
                        nosTradeDto.setRoomArea(BigDecimalADD(nosTradeDto.getRoomArea(),nosCheckDto.getRoomArea()));
                        nosTradeDto.setRoomCount(BigDecimalADD(nosTradeDto.getRoomCount(),nosCheckDto.getRoomCount()));

                        nosTradedataMap.put(nosCheckDto.getRoomId(), nosTradeDto);
                    }
                }
            }
        }

        if(CollectionUtils.isNotEmpty(nosTradedataMap)){
            for (Map.Entry<String, NosTradedataDto> rooms : nosTradedataMap.entrySet()){
                NosTradedataDto room = rooms.getValue();
                //补差信息
                NOSRoomCompensationDto nosRoomCompDto = comMap.get(room.getRoomId());
                if(nosRoomCompDto != null){
                    room.setRoomArea(BigDecimalADD(room.getRoomArea(), nosRoomCompDto.getSumArea()));
                    room.setTradeMoney(BigDecimalADD(room.getTradeMoney(), nosRoomCompDto.getSumPrice()));
                }
                String bldPrdId = room.getBuildingId();
                String product_type = room.getEstateCode();

                if(isParkList.contains(product_type)){//已售车位
                    PriceValueOrg org = soldParkingMap.get(bldPrdId);
                    if(org != null){
                        Integer num = org.getNum();
                        num++;
                        org.setNum(num);
                        org.setParkingNum(num);
                        org.setParkingSold(num);
                        BigDecimal price = BigDecimalADD(org.getPrice(), room.getTradeMoney());
                        org.setPrice(price);
                        org.setPriceSold(price);
                        org.setNotCommodityValue(price);
                        org.setAveragePriceParking(bigDecimalDIV(price, new BigDecimal(num)));
                    }else{
                        org = new PriceValueOrg();
                        org.setId(UUIDUtils.create());
                        org.setType(OrgTypeEunm.ORG_SALE_PACKAGE.getKey());
                        org.setOrgCode(OrgTypeEunm.ORG_SALE_PACKAGE.getKey());
                        org.setOrgName(OrgTypeEunm.ORG_SALE_PACKAGE.getValue());
                        org.setIsSale(IsSplitEnum.NO.getKey());
                        org.setIsSplit(IsSplitEnum.NO.getKey());
                        org.setNum(1);
                        org.setParkingNum(1);
                        org.setParkingSold(1);
                        org.setPrice(room.getTradeMoney()==null?BigDecimal.ZERO:room.getTradeMoney());
                        org.setPriceSold(room.getTradeMoney()==null?BigDecimal.ZERO:room.getTradeMoney());
                        org.setNotCommodityValue(room.getTradeMoney()==null?BigDecimal.ZERO:room.getTradeMoney());
                        org.setAveragePriceParking(org.getPrice());
                        org.setIsDelete(IsDeleteEnum.NO.getKey());
                        org.setCreateTime(now);
                    }
                    soldParkingMap.put(bldPrdId, org);
                }else{//房源
                    BigDecimal roomSaleArea = room.getRoomArea();
                    if (roomSaleArea == null){
                        roomSaleArea = BigDecimal.ZERO;
                    }
                    BigDecimal totalRoomSaleArea = areaMap.get(bldPrdId);//总可售面积
                    if(totalRoomSaleArea != null){
                        totalRoomSaleArea = BigDecimalADD(roomSaleArea, totalRoomSaleArea);
                    }else{
                        totalRoomSaleArea = roomSaleArea;
                    }
                    areaMap.put(bldPrdId, totalRoomSaleArea);

                    Integer totalRoomNum = numMap.get(bldPrdId);
                    if (totalRoomNum != null){
                        totalRoomNum ++;
                    }else{
                        totalRoomNum = 1;
                    }
                    numMap.put(bldPrdId, totalRoomNum);

                    //拆分面积段
                    for(SysDictionary dic : codes){
                        String dictValue = dic.getDictValue();
                        String dictName = dic.getDictName();

                        String[] split = dictValue.split("-");
                        Integer start = Integer.valueOf(split[0]);
                        Integer end = Integer.valueOf(split[1]);
                        if(roomSaleArea.compareTo(new BigDecimal(start)) >= 0 && roomSaleArea.compareTo(new BigDecimal(end)) < 0){

                            Map<String, PriceValueOrg> priceValueOrgMap = houseOrgMap.get(bldPrdId);
                            if(CollectionUtils.isNotEmpty(priceValueOrgMap)){
                                PriceValueOrg priceValueOrg = priceValueOrgMap.get(dictValue);
                                if(priceValueOrg != null){
                                    BigDecimal saleArea = priceValueOrg.getSaleArea();
                                    Integer roomNum = priceValueOrg.getNum();
                                    roomNum++;
                                    priceValueOrg.setNum(roomNum);
                                    priceValueOrg.setRoomNum(roomNum);

                                    //总套数
                                    Integer roomTotalNum = priceValueOrg.getTotalNum()==null?0:priceValueOrg.getTotalNum();
                                    roomTotalNum++;
                                    priceValueOrg.setTotalNum(roomTotalNum);
                                    //总面积
                                    priceValueOrg.setTotalSaleArea(BigDecimalADD(saleArea, priceValueOrg.getTotalSaleArea()));

                                    priceValueOrg.setRoomSold(roomNum);
                                    BigDecimal price = priceValueOrg.getPrice().add(room.getTradeMoney()==null?BigDecimal.ZERO:room.getTradeMoney()).setScale(4, BigDecimal.ROUND_HALF_UP);
                                    priceValueOrg.setPrice(price);
                                    priceValueOrg.setPriceSold(price);
                                    priceValueOrg.setHouseCommodityValue(price);
                                    priceValueOrg.setSaleArea(roomSaleArea.add(saleArea).setScale(4, BigDecimal.ROUND_HALF_UP));
                                    priceValueOrg.setAreaSold(roomSaleArea.add(saleArea).setScale(4, BigDecimal.ROUND_HALF_UP));
                                    priceValueOrg.setAveragePriceHouse(bigDecimalDIV(priceValueOrg.getPrice(), priceValueOrg.getSaleArea()));
                                }else{
                                    priceValueOrg = createFristSaleAreaPartOrg(now, room, roomSaleArea, dictValue, dictName);
                                }

                                priceValueOrgMap.put(dictValue, priceValueOrg);
                            }else{
                                priceValueOrgMap = new HashMap<String, PriceValueOrg>();
                                PriceValueOrg priceValueOrg = createFristSaleAreaPartOrg(now, room, roomSaleArea, dictValue, dictName);

                                priceValueOrgMap.put(dictValue, priceValueOrg);
                            }

                            houseOrgMap.put(bldPrdId, priceValueOrgMap);
                        }
                    }
                }
            }
        }

        resultMap.put("soldParkingMap", soldParkingMap);
        resultMap.put("houseOrgMap", houseOrgMap);
        resultMap.put("areaMap", areaMap);
        resultMap.put("numMap", numMap);
        return resultMap;
    }

    //创建可售面积段
    private PriceValueOrg createFristSaleAreaPartOrg(LocalDateTime now, NosTradedataDto room, BigDecimal roomSaleArea, String dictValue, String dictName) {
        PriceValueOrg priceValueOrg;
        priceValueOrg = new PriceValueOrg();
        priceValueOrg.setId(UUIDUtils.create());
        priceValueOrg.setIsSale(IsSplitEnum.NO.getKey());
        priceValueOrg.setIsSplit(IsSplitEnum.NO.getKey());
        priceValueOrg.setType(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey());
        priceValueOrg.setAreaPart(dictValue);
        priceValueOrg.setOrgName(dictName);
        //总数
        priceValueOrg.setTotalNum(1);
        priceValueOrg.setTotalSaleArea(roomSaleArea);
        priceValueOrg.setSaleArea(roomSaleArea);
        priceValueOrg.setNum(1);
        priceValueOrg.setRoomNum(1);
        BigDecimal tradeMoney = room.getTradeMoney() == null ? BigDecimal.ZERO : room.getTradeMoney();
        priceValueOrg.setPrice(tradeMoney);
        priceValueOrg.setPriceSold(tradeMoney);
        priceValueOrg.setHouseCommodityValue(tradeMoney);
        priceValueOrg.setAreaSold(roomSaleArea);
        priceValueOrg.setRoomSold(1);
        priceValueOrg.setAveragePriceHouse(bigDecimalDIV(tradeMoney, roomSaleArea));
        priceValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
        priceValueOrg.setCreateTime(now);
        return priceValueOrg;
    }

    /**
     * 货值刷新
     * @param projectFid 分期id
     * @param priceVersion 货值版本
     * @param isFinalization 是否定稿
     * @param ascriptionDate 归属月份
     * @param now 时间
     * @param source 来源
     * @param instId 报文instId
     */
    @Override
    public synchronized Map<String, String> priceRefreshActualValueInfo(String projectFid, PriceVersion priceVersion, Integer isFinalization, LocalDate ascriptionDate, LocalDateTime now, String source, String instId) {
        logger.info("#######################   priceRefreshActualValueInfo   start:"+LocalDateTime.now());
        Map<String, String> resultMap = new HashMap<String, String>();

        if(priceVersion == null){
            priceVersion = priceVersionService.selectNewestVersionByFidAndDate(projectFid, Arrays.asList(VersionTypeEunm.DYNAMIC.getKey()),
                    Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(),VersionStatusEnum.ORGANIZATION.getKey(),VersionStatusEnum.EXAMINEDAPPROVED.getKey(),
                            VersionStatusEnum.FAILUREAPPROVED.getKey(),VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey(), now);
        }

        if(priceVersion != null){

            String versionId = priceVersion.getId();
            resultMap.put(versionId, priceVersion.getVersionType());

            //查询指定分期信息
            MdmStage mdmStage = stageService.selectById(projectFid);
            if(mdmStage == null){
                throw new MsgException(CodeEnum.STAGE_NON_EXISTENT);
            }
            //查询指定货值版本中引用主数据信息
            String sourceAreaVersionStage = priceVersion.getSourceAreaVersionStage();
            String sourceAreaVersionNum = priceVersion.getSourceAreaVersionNum();
            LocalDateTime sourceAreaSysCreatedTime = priceVersion.getSourceAreaSysCreatedTime();
            String sourceGroupVersionStage = priceVersion.getSourceGroupVersionStage();
            String sourceGroupVersionCode = priceVersion.getSourceGroupVersionCode();
            LocalDateTime sourceGroupCreateTime = priceVersion.getSourceGroupCreateTime();

            //查询指定主数据信息
            MdmBuildAreaBO mdmProductWarPlanBO = buildAreaService.selectAppoint(projectFid, sourceAreaVersionStage, sourceAreaVersionNum, sourceAreaSysCreatedTime,
                    sourceGroupVersionStage, sourceGroupVersionCode, sourceGroupCreateTime);
            if(mdmProductWarPlanBO == null){
                throw new MsgException(CodeEnum.NON_APPOINT_GROUPBLD_AREA);
            }

            //查询指定货值版本中引用楼栋计划信息
            String sourcePlan = priceVersion.getSourcePlan();

            //获取最新的战规版楼栋计划
            PanoPlanCastDecisionBO panoPlanCastDecisionBO = panoplanBuildPlanService.selectById(sourcePlan);

            Map<String, String> panoplanBuildPlanItemMap = new HashMap<>();
            Map<String, PanoplanBuildPlanItem> panoplanItemMap = new HashMap<>();
            mdmToPanoBuildVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO, panoplanBuildPlanItemMap, panoplanItemMap);

            //楼栋计划匹配节点
            Map<String, LocalDateTime> openTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> openTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> advanceSaleTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> advanceSaleTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> supplyTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> supplyTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> supplyTimeVirtualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> openSaleTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> openSaleTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> cappingTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> cappingTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> completedTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> completedTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> carryOverTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> carryOverTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> actualDeliveryTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> actualDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> contractDeliveryTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> contractDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
            panoTimeItemNodeMapInfo(panoPlanCastDecisionBO, panoplanBuildPlanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap);

            //查询取数系统
            String fetchSysCode = priceVersion.getCountingSystemCode();

            Map<String, PriceValueOrg> presaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已售车位
            Map<String, PriceValueOrg> prenotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已定价未售车位
            Map<String, PriceValueOrg> preSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版可售车位
            Map<String, PriceValueOrg> preNotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版未推售车位
            Map<String, List<PriceValueOrg>> preHouseMap = new HashMap<String, List<PriceValueOrg>>(); //上一版房源包
            Map<String, PriceValueOrg> preBuildMap = new HashMap<String, PriceValueOrg>(); //上一版楼栋
            Map<String, BigDecimal> preBuildAvPriceMap = new HashMap<String, BigDecimal>();//上一版楼栋均价
            List<PriceValueCastDecisionAllOrgEXTBO> priceValueCastDecisionAllOrgEXTBOS = priceValueOrgMapper.selectHouseAndPark(priceVersion.getId(), IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isNotEmpty(priceValueCastDecisionAllOrgEXTBOS)) {
                priceRefreshPreOrgInfo(presaleParkMap, prenotSaleParkMap, preSaleParkMap, preNotSaleParkMap, preHouseMap, priceValueCastDecisionAllOrgEXTBOS);
            }

            List<PriceValueOrg> oldBuildList = priceValueOrgService.selectBuildByVersionId(priceVersion.getId(), OrgTypeEunm.ORG_BUILD.getKey(), null, IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isNotEmpty(oldBuildList)){
                for (PriceValueOrg oldBuild : oldBuildList){
                    preBuildMap.put(oldBuild.getOrgId(), oldBuild);
                    if (oldBuild.getIsParking().equals(IsDeleteEnum.NO.getKey())){
                        preBuildAvPriceMap.put(oldBuild.getOrgId(), oldBuild.getAveragePriceHouse());
                    }else{
                        preBuildAvPriceMap.put(oldBuild.getOrgId(), oldBuild.getAveragePriceParking());
                    }
                }
            }

            //创建新版本
            PriceVersionBackups priceVersionBackups = new PriceVersionBackups();
            BeanUtils.copyProperties(priceVersion, priceVersionBackups);
            String oldVersionState = priceRefreshVersionInfo(priceVersion, isFinalization, ascriptionDate, now, source, instId, priceVersionBackups);

            //创建分期
            PriceValueOrg projectOrg = createStageValueInfo(now, mdmStage, priceVersion.getId());

            //创建组团
            Map<String, PriceValueOrg> groupMap = new HashMap<String, PriceValueOrg>();
            Map<String, PriceValueOrg> groupInsertMap = new HashMap<String, PriceValueOrg>();
            List<MdmBuildAreaDetailBO> groupItems = mdmProductWarPlanBO.getGroupItems();
            for(MdmBuildAreaDetailBO groupItem : groupItems){
                dynamicVersionGroupItemInfo(now, priceVersion, projectOrg, groupMap, groupInsertMap, groupItem);
            }

            //创建产品构成
            Map<String, PriceValueOrg> productMap = new HashMap<String, PriceValueOrg>();
            Map<String, PriceValueOrg> productInsertMap = new HashMap<String, PriceValueOrg>();
            List<MdmBuildAreaDetailBO> productItems = mdmProductWarPlanBO.getProductItems();

            //寻找上级分类
            dynamicVersionProductToDic(now, priceVersion, groupMap, productMap, productInsertMap, productItems);

            //创建楼栋
            List<String> parkingBuildList = new ArrayList<>();
            List<PriceValueOrg> buildList = new ArrayList<PriceValueOrg>();
            List<PriceValueOrg> notSalyTypeList = new ArrayList<PriceValueOrg>();
            for(MdmBuildAreaDetailBO buildItem : mdmProductWarPlanBO.getBuildItems()) {
                dynamicVersionBuildItemInfo(priceVersion, now, panoplanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, productMap, parkingBuildList, buildList, notSalyTypeList, buildItem);
            }

            //查看取数系统
            Map<String, PriceValueOrg> soldParkingMap = new HashMap<String, PriceValueOrg>();
            Map<String, PriceValueOrg> notSoldParkingOrgMap = new HashMap<String, PriceValueOrg>();
            Map<String, Map<String ,PriceValueOrg>> houseOrgMap = new HashMap<String, Map<String ,PriceValueOrg>>();
            Map<String, BigDecimal> areaMap = new HashMap<>();
            Map<String, Integer> numMap = new HashMap<>();

            //自持信息
            Map<String, Integer> zcParkingNumMap = new HashMap<>();//楼栋下自持房源套数
            Map<String, BigDecimal> zcParkingPriceMap = new HashMap<>();//楼栋下自持房源面积

            //收集面积段
            if (fetchSysCode.equals(FetchNnumberEnum.MY.getKey())){
            	//TODO 明源签约数据改成ESB下发，生产上线此处projectFid应改成 mdmStage.getKingdeeProjectfId()
                Map<String, Map> houseParkMap = myCollectHouse(projectFid, mdmStage.getKingdeeProjectfId(), parkingBuildList, preBuildAvPriceMap, now,null);
                soldParkingMap = houseParkMap.get("soldParkingMap");
                notSoldParkingOrgMap = houseParkMap.get("notSoldParkingOrgMap");
                houseOrgMap = houseParkMap.get("houseOrgMap");
                areaMap = houseParkMap.get("areaMap");
                numMap = houseParkMap.get("numMap");

                zcParkingNumMap = houseParkMap.get("zcParkingNumMap");
                zcParkingPriceMap = houseParkMap.get("zcParkingPriceMap");
            }else if(fetchSysCode.equals(FetchNnumberEnum.NOS.getKey())){
                Map<String, Map> houseParkMap = nosCollectHouse(mdmStage.getKingdeeProjectfId(), now,null);
                soldParkingMap = houseParkMap.get("soldParkingMap");
                houseOrgMap = houseParkMap.get("houseOrgMap");
                areaMap = houseParkMap.get("areaMap");
                numMap = houseParkMap.get("numMap");
            }

            //是否有销售货值
            if (CollectionUtils.isNotEmpty(houseOrgMap) || CollectionUtils.isNotEmpty(soldParkingMap) || CollectionUtils.isNotEmpty(notSoldParkingOrgMap)){
                priceVersion.setIsContainSale(IsDeleteEnum.YES.getKey());
            }else{
                priceVersion.setIsContainSale(IsDeleteEnum.NO.getKey());
            }

            List<PriceValueOrg> buildInsertList = new ArrayList<PriceValueOrg>();
            List<PriceValueOrg> hoseSoleList = new ArrayList<PriceValueOrg>();
            List<PriceValueOrg> sortParkList = new ArrayList<PriceValueOrg>();

            //赋值楼栋货值
            for (PriceValueOrg buildOrg : buildList) {
                priceRefreshBuildToOtherItemInfo(priceVersion, now, versionId, fetchSysCode, preSaleParkMap, preHouseMap, preBuildMap, soldParkingMap, notSoldParkingOrgMap, houseOrgMap, areaMap, numMap, zcParkingNumMap, zcParkingPriceMap, buildInsertList, hoseSoleList, sortParkList, buildOrg);
            }

            //货值汇总
            List<PriceValueOrg> groupInsertList = new ArrayList<PriceValueOrg>();
            List<PriceValueOrg> productInsertList = new ArrayList<PriceValueOrg>();
            if (CollectionUtils.isNotEmpty(buildInsertList)){
                dynamicVersionSumInfo(projectOrg, groupInsertMap, productInsertMap, buildInsertList, groupInsertList, productInsertList);
            }
            List<PriceValueOrg> projectList = Arrays.asList(projectOrg);

            //保存
            priceVersionService.refreshSaveInfo(priceVersion,projectList,groupInsertList,productInsertList,buildInsertList,hoseSoleList,sortParkList,now);

            try{
                priceVersionBackupsService.refreshSaveInfo(priceVersion,priceVersionBackups,now);
            }catch (Exception e){
                logger.error("################ refresh price versionBackups error : "+e);
            }

            //修改添加代办消息
            String taskName = "";
            taskName = priceRefreshCreateNoticeInfo(priceVersion, now, source, instId, versionId, taskName);

            try{
                versionLogService.saveVersionLogInfo(priceVersion.getProjectId(), priceVersion.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), VersionEventEnum.SYS_REFRESH.getKey(), priceVersion.getId(), VersionNameUtils.getVersionName(priceVersion), oldVersionState,
                        priceVersion.getVersionState(), "1", instId, Constants.SYS, now, "货值下游系统刷新版本:"+taskName, null, IsDeleteEnum.NO.getKey(), Constants.SYS, now);
            }catch (Exception e){
                logger.error("################ refresh price version versionLog error : "+e);
            }
        }

        return resultMap;
    }
    
    
    /**
     * 货值刷新
     * @param projectFid 分期id
     * @param priceVersion 货值版本
     * @param isFinalization 是否定稿
     * @param ascriptionDate 归属月份
     * @param now 时间
     * @param source 来源
     * @param instId 报文instId
     */
    public synchronized Map<String, String> priceRefreshActual(String projectFid, PriceVersion priceVersion,Integer isFinalization,LocalDateTime now, String source, String instId) {
        Map<String, String> resultMap = new HashMap<String, String>();
        if(priceVersion != null){
            String versionId = priceVersion.getId();
            resultMap.put(versionId, priceVersion.getVersionType());
            //查询指定分期信息
            MdmStage mdmStage = stageService.selectById(projectFid);
            if(mdmStage == null){
                throw new MsgException(CodeEnum.STAGE_NON_EXISTENT);
            }
            //查询指定货值版本中引用主数据信息
            String sourceAreaVersionStage = priceVersion.getSourceAreaVersionStage();
            String sourceAreaVersionNum = priceVersion.getSourceAreaVersionNum();
            LocalDateTime sourceAreaSysCreatedTime = priceVersion.getSourceAreaSysCreatedTime();
            String sourceGroupVersionStage = priceVersion.getSourceGroupVersionStage();
            String sourceGroupVersionCode = priceVersion.getSourceGroupVersionCode();
            LocalDateTime sourceGroupCreateTime = priceVersion.getSourceGroupCreateTime();
            
            LocalDateTime ModifiedTime = priceVersion.getUpdateTime();

            //查询指定主数据信息
            MdmBuildAreaBO mdmProductWarPlanBO = buildAreaService.selectAppoint(projectFid, sourceAreaVersionStage, sourceAreaVersionNum, sourceAreaSysCreatedTime,
                    sourceGroupVersionStage, sourceGroupVersionCode, sourceGroupCreateTime);
            if(mdmProductWarPlanBO == null){
                throw new MsgException(CodeEnum.NON_APPOINT_GROUPBLD_AREA);
            }

            //查询指定货值版本中引用楼栋计划信息
            String sourcePlan = priceVersion.getSourcePlan();
            //获取最新的战规版楼栋计划
            PanoPlanCastDecisionBO panoPlanCastDecisionBO = panoplanBuildPlanService.selectById(sourcePlan);

            Map<String, String> panoplanBuildPlanItemMap = new HashMap<>();
            Map<String, PanoplanBuildPlanItem> panoplanItemMap = new HashMap<>();
            mdmToPanoBuildVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO, panoplanBuildPlanItemMap, panoplanItemMap);

            //楼栋计划匹配节点
            Map<String, LocalDateTime> openTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> openTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> advanceSaleTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> advanceSaleTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> supplyTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> supplyTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> supplyTimeVirtualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> openSaleTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> openSaleTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> cappingTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> cappingTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> completedTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> completedTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> carryOverTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> carryOverTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> actualDeliveryTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> actualDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> contractDeliveryTimeMap = new HashMap<String, LocalDateTime>();
            Map<String, LocalDateTime> contractDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
            panoTimeItemNodeMapInfo(panoPlanCastDecisionBO, panoplanBuildPlanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap);

            //查询取数系统
            String fetchSysCode = priceVersion.getCountingSystemCode();

            Map<String, PriceValueOrg> presaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已售车位
            Map<String, PriceValueOrg> prenotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已定价未售车位
            Map<String, PriceValueOrg> preSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版可售车位
            Map<String, PriceValueOrg> preNotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版未推售车位
            Map<String, List<PriceValueOrg>> preHouseMap = new HashMap<String, List<PriceValueOrg>>(); //上一版房源包
            Map<String, PriceValueOrg> preBuildMap = new HashMap<String, PriceValueOrg>(); //上一版楼栋
            Map<String, BigDecimal> preBuildAvPriceMap = new HashMap<String, BigDecimal>();//上一版楼栋均价
            List<PriceValueCastDecisionAllOrgEXTBO> priceValueCastDecisionAllOrgEXTBOS = priceValueOrgMapper.selectHouseAndPark(priceVersion.getId(), IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isNotEmpty(priceValueCastDecisionAllOrgEXTBOS)) {
                priceRefreshPreOrgInfo(presaleParkMap, prenotSaleParkMap, preSaleParkMap, preNotSaleParkMap, preHouseMap, priceValueCastDecisionAllOrgEXTBOS);
            }

            List<PriceValueOrg> oldBuildList = priceValueOrgService.selectBuildByVersionId(priceVersion.getId(), OrgTypeEunm.ORG_BUILD.getKey(), null, IsDeleteEnum.NO.getKey());
            if (CollectionUtils.isNotEmpty(oldBuildList)){
                for (PriceValueOrg oldBuild : oldBuildList){
                    preBuildMap.put(oldBuild.getOrgId(), oldBuild);
                    if (oldBuild.getIsParking().equals(IsDeleteEnum.NO.getKey())){
                        preBuildAvPriceMap.put(oldBuild.getOrgId(), oldBuild.getAveragePriceHouse());
                    }else{
                        preBuildAvPriceMap.put(oldBuild.getOrgId(), oldBuild.getAveragePriceParking());
                    }
                }
            }

            //创建新版本
            PriceVersionBackups priceVersionBackups = new PriceVersionBackups();
            BeanUtils.copyProperties(priceVersion, priceVersionBackups);

            //创建分期
            PriceValueOrg projectOrg = createStageValueInfo(now, mdmStage, priceVersion.getId());

            //创建组团
            Map<String, PriceValueOrg> groupMap = new HashMap<String, PriceValueOrg>();
            Map<String, PriceValueOrg> groupInsertMap = new HashMap<String, PriceValueOrg>();
            List<MdmBuildAreaDetailBO> groupItems = mdmProductWarPlanBO.getGroupItems();
            for(MdmBuildAreaDetailBO groupItem : groupItems){
                dynamicVersionGroupItemInfo(now, priceVersion, projectOrg, groupMap, groupInsertMap, groupItem);
            }

            //创建产品构成
            Map<String, PriceValueOrg> productMap = new HashMap<String, PriceValueOrg>();
            Map<String, PriceValueOrg> productInsertMap = new HashMap<String, PriceValueOrg>();
            List<MdmBuildAreaDetailBO> productItems = mdmProductWarPlanBO.getProductItems();

            //寻找上级分类
            dynamicVersionProductToDic(now, priceVersion, groupMap, productMap, productInsertMap, productItems);

            //创建楼栋
            List<String> parkingBuildList = new ArrayList<>();
            List<PriceValueOrg> buildList = new ArrayList<PriceValueOrg>();
            List<PriceValueOrg> notSalyTypeList = new ArrayList<PriceValueOrg>();
            for(MdmBuildAreaDetailBO buildItem : mdmProductWarPlanBO.getBuildItems()) {
                dynamicVersionBuildItemInfo(priceVersion, now, panoplanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, productMap, parkingBuildList, buildList, notSalyTypeList, buildItem);
            }

            //查看取数系统
            Map<String, PriceValueOrg> soldParkingMap = new HashMap<String, PriceValueOrg>();
            Map<String, PriceValueOrg> notSoldParkingOrgMap = new HashMap<String, PriceValueOrg>();
            Map<String, Map<String ,PriceValueOrg>> houseOrgMap = new HashMap<String, Map<String ,PriceValueOrg>>();
            Map<String, BigDecimal> areaMap = new HashMap<>();
            Map<String, Integer> numMap = new HashMap<>();

            //自持信息
            Map<String, Integer> zcParkingNumMap = new HashMap<>();//楼栋下自持房源套数
            Map<String, BigDecimal> zcParkingPriceMap = new HashMap<>();//楼栋下自持房源面积

            //收集面积段
            if (fetchSysCode.equals(FetchNnumberEnum.MY.getKey())){
            	//TODO 明源签约数据改成ESB下发，生产上线此处projectFid应改成 mdmStage.getKingdeeProjectfId()
                Map<String, Map> houseParkMap = myCollectHouse(projectFid, mdmStage.getKingdeeProjectfId(), parkingBuildList, preBuildAvPriceMap, now,ModifiedTime);
                soldParkingMap = houseParkMap.get("soldParkingMap");
                notSoldParkingOrgMap = houseParkMap.get("notSoldParkingOrgMap");
                houseOrgMap = houseParkMap.get("houseOrgMap");
                areaMap = houseParkMap.get("areaMap");
                numMap = houseParkMap.get("numMap");

                zcParkingNumMap = houseParkMap.get("zcParkingNumMap");
                zcParkingPriceMap = houseParkMap.get("zcParkingPriceMap");
            }else if(fetchSysCode.equals(FetchNnumberEnum.NOS.getKey())){
                Map<String, Map> houseParkMap = nosCollectHouse(mdmStage.getKingdeeProjectfId(), now,null);
                soldParkingMap = houseParkMap.get("soldParkingMap");
                houseOrgMap = houseParkMap.get("houseOrgMap");
                areaMap = houseParkMap.get("areaMap");
                numMap = houseParkMap.get("numMap");
            }

            //是否有销售货值
            if (CollectionUtils.isNotEmpty(houseOrgMap) || CollectionUtils.isNotEmpty(soldParkingMap) || CollectionUtils.isNotEmpty(notSoldParkingOrgMap)){
                priceVersion.setIsContainSale(IsDeleteEnum.YES.getKey());
            }else{
                priceVersion.setIsContainSale(IsDeleteEnum.NO.getKey());
            }

            List<PriceValueOrg> buildInsertList = new ArrayList<PriceValueOrg>();
            List<PriceValueOrg> hoseSoleList = new ArrayList<PriceValueOrg>();
            List<PriceValueOrg> sortParkList = new ArrayList<PriceValueOrg>();

            //赋值楼栋货值
            for (PriceValueOrg buildOrg : buildList) {
                priceRefreshBuildToOtherItemInfo(priceVersion, now, versionId, fetchSysCode, preSaleParkMap, preHouseMap, preBuildMap, soldParkingMap, notSoldParkingOrgMap, houseOrgMap, areaMap, numMap, zcParkingNumMap, zcParkingPriceMap, buildInsertList, hoseSoleList, sortParkList, buildOrg);
            }
            //货值汇总
            List<PriceValueOrg> groupInsertList = new ArrayList<PriceValueOrg>();
            List<PriceValueOrg> productInsertList = new ArrayList<PriceValueOrg>();
            if (CollectionUtils.isNotEmpty(buildInsertList)){
                dynamicVersionSumInfo(projectOrg, groupInsertMap, productInsertMap, buildInsertList, groupInsertList, productInsertList);
            }
            List<PriceValueOrg> projectList = Arrays.asList(projectOrg);
            //保存
            priceVersionService.refreshSaveInfo(priceVersion,projectList,groupInsertList,productInsertList,buildInsertList,hoseSoleList,sortParkList,now);
        }
        return resultMap;
    }
    
    

    protected void priceRefreshPreOrgInfo(Map<String, PriceValueOrg> presaleParkMap, Map<String, PriceValueOrg> prenotSaleParkMap, Map<String, PriceValueOrg> preSaleParkMap, Map<String, PriceValueOrg> preNotSaleParkMap, Map<String, List<PriceValueOrg>> preHouseMap, List<PriceValueCastDecisionAllOrgEXTBO> priceValueCastDecisionAllOrgEXTBOS) {
        for (PriceValueCastDecisionAllOrgEXTBO preValueOrg : priceValueCastDecisionAllOrgEXTBOS) {
            String type = preValueOrg.getType();
            if (type.equals(OrgTypeEunm.ORG_HOUSE_PACKAGE.getKey())) {
                List<PriceValueOrg> valueOrgs = preHouseMap.get(preValueOrg.getCode());
                if (CollectionUtils.isEmpty(valueOrgs)) {
                    valueOrgs = new ArrayList<PriceValueOrg>();
                }
                valueOrgs.add(preValueOrg);
                preHouseMap.put(preValueOrg.getCode(), valueOrgs);
            } else if (type.equals(OrgTypeEunm.ORG_SALE_PACKAGE.getKey())) {
                presaleParkMap.put(preValueOrg.getCode(), preValueOrg);
            } else if (type.equals(OrgTypeEunm.ORG_NOT_SALE_PACKAGE.getKey())) {
                prenotSaleParkMap.put(preValueOrg.getCode(), preValueOrg);
            } else if (type.equals(OrgTypeEunm.ORG_SALING_PARKING.getKey())) {
                preSaleParkMap.put(preValueOrg.getCode(), preValueOrg);
            } else if (type.equals(OrgTypeEunm.ORG_NOT_SALING_PARKING.getKey())) {
                preNotSaleParkMap.put(preValueOrg.getCode(), preValueOrg);
            }
        }
    }

    protected String priceRefreshVersionInfo(PriceVersion priceVersion, Integer isFinalization, LocalDate ascriptionDate, LocalDateTime now, String source, String instId, PriceVersionBackups priceVersionBackups) {
        priceVersionBackups.setId(UUIDUtils.create());
        priceVersionBackups.setVersionId(priceVersion.getId());
        priceVersionBackups.setUpdateTime(now);

        if(StringUtils.isNotEmpty(source) && source.equals(Constants.MY)){
            priceVersion.setRemake("明源实际数据刷新");
            priceVersionBackups.setBackupsExplain("明源实际数据刷新:"+instId);
        }else if (StringUtils.isNotEmpty(source) && source.equals(Constants.NOS)){
            priceVersion.setRemake("NOS实际数据刷新");
            priceVersionBackups.setBackupsExplain("NOS实际数据刷新:"+instId);
        }else if (StringUtils.isNotEmpty(source) && source.equals(Constants.CLICK)){
            priceVersion.setRemake("指定分期实际数据刷新");
            priceVersionBackups.setBackupsExplain("指定分期实际数据刷新");
        }else{
            priceVersion.setRemake("定稿刷新");
            priceVersionBackups.setBackupsExplain("定稿刷新");
        }

        //定稿
        if (isFinalization != null && isFinalization == 1){
            priceVersion.setIsFinalization(isFinalization);
            priceVersion.setAscriptionDate(ascriptionDate);
            priceVersion.setRemake("定稿");
            priceVersion.setUpdateBy(Constants.SYS);
            priceVersion.setUpdateTime(LocalDateTime.now());
        }

        priceVersion.setUpdateBy(Constants.SYS);
        priceVersion.setUpdateTime(now);

        //如果版本状态为编制中，版本状态为代编制
        String oldVersionState = priceVersion.getVersionState();
        if(priceVersion.getVersionState().equals(VersionStatusEnum.ORGANIZATION.getKey())){
            priceVersion.setVersionState(VersionStatusEnum.NOTPREPARED.getKey());
        }
        return oldVersionState;
    }

    protected void priceRefreshBuildToOtherItemInfo(PriceVersion priceVersion, LocalDateTime now, String versionId, String fetchSysCode, Map<String, PriceValueOrg> preSaleParkMap, Map<String, List<PriceValueOrg>> preHouseMap, Map<String, PriceValueOrg> preBuildMap, Map<String, PriceValueOrg> soldParkingMap, Map<String, PriceValueOrg> notSoldParkingOrgMap, Map<String, Map<String, PriceValueOrg>> houseOrgMap, Map<String, BigDecimal> areaMap, Map<String, Integer> numMap, Map<String, Integer> zcParkingNumMap, Map<String, BigDecimal> zcParkingPriceMap, List<PriceValueOrg> buildInsertList, List<PriceValueOrg> hoseSoleList, List<PriceValueOrg> sortParkList, PriceValueOrg buildOrg) {
        String buildId = buildOrg.getId();
        String buildOrgId = buildOrg.getOrgId();
        Integer isParking = buildOrg.getIsParking();
        Integer buildNum = buildOrg.getNum()==null?0:buildOrg.getNum();
        BigDecimal buildArea = buildOrg.getSaleArea()==null?new BigDecimal(0):buildOrg.getSaleArea();
        String businessType = buildOrg.getBusinessType();

        //如果楼栋是 不可租售 或 可租，则不复制信息
        if (businessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()) || businessType.equals(SalyTypeEnum.RENTED.getKey())){
            buildInsertList.add(buildOrg);
            return;
        }

        //赋值上版本楼栋信息
        PriceValueOrg oldBuildOrg = preBuildMap.get(buildOrgId);
        if (oldBuildOrg != null){
            buildOrg.setAveragePriceParking(oldBuildOrg.getAveragePriceParking());
            buildOrg.setAveragePriceHouse(oldBuildOrg.getAveragePriceHouse());

            if(isParking == IsDeleteEnum.YES.getKey()){
                buildOrg.setNotCommodityValue(BigDecimalMUL(oldBuildOrg.getAveragePriceParking(), new BigDecimal(buildNum)));
                buildOrg.setCommodityValue(oldBuildOrg.getCommodityValue());
            }else{
                buildOrg.setHouseCommodityValue(BigDecimalMUL(oldBuildOrg.getAveragePriceHouse(), buildOrg.getSaleArea()));
            }
        }

        //车位信息
        if(isParking == IsDeleteEnum.YES.getKey()){
            parkingCollectInfo(now, preSaleParkMap, preBuildMap, soldParkingMap, notSoldParkingOrgMap, numMap, zcParkingNumMap, zcParkingPriceMap, sortParkList, buildOrg, buildId, versionId, buildOrgId, buildNum, buildInsertList);
        }else{
            //归集收集房源包
            Map<String, PriceValueOrg> roomPriceValueOrgMap = houseOrgMap.get(buildOrgId);

            if (fetchSysCode.equals(FetchNnumberEnum.NOS.getKey()) || CollectionUtils.isEmpty(roomPriceValueOrgMap)){
                //部分归集面积段
                areaPartCollectInfo(now, preHouseMap, priceVersion.getId(), houseOrgMap, buildInsertList, hoseSoleList, buildOrg, buildId, buildOrgId, buildNum, buildArea, oldBuildOrg, numMap, areaMap);
            }else{
                //全部归集面积段
                allAreaPartCollectInfo(areaMap, numMap, buildInsertList, hoseSoleList, buildOrg, buildId, versionId, buildOrgId, roomPriceValueOrgMap);
            }
        }
    }

    private void dynamicVersionBuildItemInfo(PriceVersion priceVersion, LocalDateTime now, Map<String, PanoplanBuildPlanItem> panoplanItemMap, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap, Map<String, PriceValueOrg> productMap, List<String> parkingBuildList, List<PriceValueOrg> buildList, List<PriceValueOrg> notSalyTypeList, MdmBuildAreaDetailBO buildItem) {
        PriceValueOrg buildOrg = createBuildValueInfo(now, panoplanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, priceVersion.getId(), productMap, parkingBuildList, buildItem);

        String businessType = buildItem.getBusinessType();
        if (businessType != null && (businessType.equals(SalyTypeEnum.RENTED.getKey()) || businessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()))) {
            notSalyTypeList.add(buildOrg);
        }

        buildList.add(buildOrg);
    }

    private void dynamicVersionProductItemInfo(PriceVersion priceVersion, LocalDateTime now, Map<String, PriceValueOrg> groupMap, Map<String, PriceValueOrg> productMap, Map<String, PriceValueOrg> productInsertMap, Map<String, DictionaryCodeBO> dicMap, MdmBuildAreaDetailBO productItem) {
        PriceValueOrg productOrg = createProductValueInfo(now, priceVersion.getId(), groupMap, dicMap, productItem);

        productMap.put(productItem.getGroupId() + "&" + productItem.getProductCode(), productOrg);
        productInsertMap.put(productOrg.getId(), productOrg);
    }

    //处理待办消息
    private String priceRefreshCreateNoticeInfo(PriceVersion priceVersion, LocalDateTime now, String source, String instId, String versionId, String taskName) {
        try{
            if(StringUtils.isNotEmpty(source) && source.equals(Constants.MY)){
                taskName = Constants.NOTICE_MY_REFRESH;
            }else if(StringUtils.isNotEmpty(source) && source.equals(Constants.NOS)){
                taskName = Constants.NOTICE_NOS_REFRESH;
            }else if(StringUtils.isNotEmpty(source) && source.equals(Constants.CLICK)){
                taskName = Constants.NOTICE_CLICK_REFRESH;
            }else{
                taskName = Constants.NOTICE_DG_REFRESH;
            }

            mymRoomInfoServiceImpl.noticeDownsRecordProcessedInfo(taskName, instId, versionId, priceVersion.getProjectId(), priceVersion.getProjectfId(), ProcessingStateEnum.PROCESSED.getKey(), ProcessingModeEnum.SYSTEM.getKey(), source, now);
        }catch (Exception e){
            logger.error("################ 添加代办消息 error :"+e.getMessage(), e);
        }
        return taskName;
    }

    /**
     * 战规后版本对比
     * @param stagesId 分期id
     * @param taskSource 代办任务来源
     * @return NoticePriceCompareVo 货值版本变动代办详情信息
     */
    @Override
    public NoticePriceCompareVo dynamicVersionCompare(String stagesId, String taskSource) {

        NoticePriceCompareVo noticePriceCompareVo = new NoticePriceCompareVo();

        List<PriceValueCompareVO> resultList = new ArrayList<PriceValueCompareVO>();

        //查询指定分期信息
        MdmStage mdmStage = stageService.selectById(stagesId);
        if(mdmStage == null){
            throw new MsgException(CodeEnum.STAGE_NON_EXISTENT);
        }

        //获取最新的动态版楼栋计划
        PanoPlanCastDecisionBO panoPlanCastDecisionBO = panoplanBuildPlanService.selectNewestWarPlanByFid(stagesId, taskSource, IsDeleteEnum.NO.getKey());

        //获取最新的动态版楼栋面积
        MdmBuildAreaBO mdmProductWarPlanBO = buildAreaService.selectNewestByFid(stagesId, taskSource, IsDeleteEnum.NO.getKey());
        if(mdmProductWarPlanBO == null){
            throw new MsgException(CodeEnum.NON_GROUPBLD_AREA);
        }

        //全景计划系统最新版楼栋计划项目树与主数据系统最新版面积版本项目树不匹配，不允许创建新版本；
        mdmToPanoGroupVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO);

        mdmToPanoProductVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO);

        Map<String, String> panoplanBuildPlanItemMap = new HashMap<>();
        Map<String, PanoplanBuildPlanItem> panoplanItemMap = new HashMap<>();
        Map<String, String> panoplanItemIdMap = new HashMap<>();
        if(panoPlanCastDecisionBO.getBuildItems().size() == mdmProductWarPlanBO.getBuildItems().size()){
            List<String> buildList = new ArrayList<String>();
            for(PanoplanBuildPlanItem buildItem : panoPlanCastDecisionBO.getBuildItems()){
                buildList.add(buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId());
                panoplanBuildPlanItemMap.put(buildItem.getId(), buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId());
                panoplanItemMap.put(buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId(), buildItem);
                panoplanItemIdMap.put(buildItem.getId(), buildItem.getBatchId() + "&" + buildItem.getProductTypeNum() + "&" + buildItem.getBldPrdId());
            }

            for(MdmBuildAreaDetailBO buildAreaBO : mdmProductWarPlanBO.getBuildItems()){
                if(buildList.contains(buildAreaBO.getGroupId()+"&"+buildAreaBO.getProductCode()+"&"+buildAreaBO.getBldPrdId())){
                    String businessType = buildAreaBO.getBusinessType();
                    if (businessType.equals(SalyTypeEnum.SALABLE.getKey()) ||
                            businessType.equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey()) ){
                        BigDecimal totalSaleArea = buildAreaBO.getTotalSaleArea()==null?new BigDecimal(0):buildAreaBO.getTotalSaleArea();
                        if(!isParkList.contains(buildAreaBO.getProductCode())){
                            if (totalSaleArea.compareTo(new BigDecimal(0)) <= 0 ){
                                String message = "楼栋信息不完整:"+buildAreaBO.getFormatBuildingName()+"面积小于等于0";
                                CodeEnum.NON_PANOPLAN_BUILD.setMessage(message);
                                throw new MsgException(CodeEnum.NON_PANOPLAN_BUILD);
                            }
                        }

                        Integer roomNum = buildAreaBO.getRoomNum()==null?0:buildAreaBO.getRoomNum();
                        if (roomNum <= 0){
                            if (!isParkList.contains(buildAreaBO.getProductCode())){
                                String message = "楼栋信息不完整:"+buildAreaBO.getFormatBuildingName()+"套数/个数小于等于0";
                                CodeEnum.NON_PANOPLAN_BUILD.setMessage(message);
                                throw new MsgException(CodeEnum.NON_PANOPLAN_BUILD);
                            }
                        }
                    }

                    buildList.remove(buildAreaBO.getGroupId()+"&"+buildAreaBO.getProductCode()+"&"+buildAreaBO.getBldPrdId());
                }else{
                    throw new MsgException(CodeEnum.NON_MATCH_VERSIONS);
                }
            }

            if(CollectionUtils.isNotEmpty(buildList)){
                throw new MsgException(CodeEnum.NON_MATCH_VERSIONS);
            }
        }else{
            throw new MsgException(CodeEnum.NON_ORG_VERSIONS);
        }

        //查询全盘最新货值信息
        PriceVersion newestPriceVersion = priceVersionMapper.selectNewestVersionByFidAndTypes(mdmStage.getProjectFid(), Arrays.asList(VersionTypeEunm.DYNAMIC.getKey(), VersionTypeEunm.GETPRICE.getKey(), VersionTypeEunm.WARPLAN.getKey()),
                Arrays.asList(VersionStatusEnum.NOTPREPARED.getKey(), VersionStatusEnum.ORGANIZATION.getKey(), VersionStatusEnum.EXAMINEDAPPROVED.getKey(),
                        VersionStatusEnum.APPROVED.getKey(), VersionStatusEnum.FAILUREAPPROVED.getKey(), VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey());
        if(newestPriceVersion == null){
            noticePriceCompareVo.setCompareMsg(CodeEnum.NON_COMPARRE_ERROR.getMessage());
            return noticePriceCompareVo;
        }
        noticePriceCompareVo.setVersionState(newestPriceVersion.getVersionState());

        //如果货值为审批中，则添加流程实例ID
        if(newestPriceVersion.getVersionState().equals(VersionStatusEnum.APPROVED.getKey())){
            ApprovalBill approvalBill = approvalBillMapper.selectBillByVersionId(newestPriceVersion.getId());
            if(approvalBill != null){
                noticePriceCompareVo.setInstanceId(approvalBill.getInstanceId());
            }
        }

        //查询货值楼栋信息数据
        Map<String, PriceValueCastDecisionAllOrgEXTBO> extValueBuildMap = new HashMap<String, PriceValueCastDecisionAllOrgEXTBO>();
        List<PriceValueCastDecisionAllOrgEXTBO> newestBuildList = priceValueOrgMapper.selectWPBuildOrgByVersionId(newestPriceVersion.getId(), IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(newestBuildList)){
            for (PriceValueCastDecisionAllOrgEXTBO extBuild : newestBuildList) {
                extValueBuildMap.put(extBuild.getCode()+"&"+extBuild.getOrgId(), extBuild);
            }
        }

        //比较主数据楼栋信息和货值楼栋信息是否一致
        List<PriceValueCompareVO> buildCompareVOList = new ArrayList<PriceValueCompareVO>();
        wc : for (MdmBuildAreaDetailBO mdmBuildItem : mdmProductWarPlanBO.getBuildItems()){
            String code = mdmBuildItem.getGroupId()+"&"+mdmBuildItem.getProductCode()+"&"+mdmBuildItem.getBldPrdId();

            PriceValueCompareVO buildCompareVO = new PriceValueCompareVO();
            buildCompareVO.setId(UUIDUtils.create());
            buildCompareVO.setType(OrgTypeEunm.ORG_BUILD.getKey());
            buildCompareVO.setName(mdmBuildItem.getFormatBuildingName());
            buildCompareVO.setCode(mdmBuildItem.getGroupId()+"&"+mdmBuildItem.getProductCode());

            //是否车位楼栋
            boolean isparking = isParkList.contains(mdmBuildItem.getProductCode());
            if (isparking){
                buildCompareVO.setIsParking(IsDeleteEnum.YES.getKey());
            }else {
                buildCompareVO.setIsParking(IsDeleteEnum.NO.getKey());
            }

            PriceValueCastDecisionAllOrgEXTBO valueBuildItem = extValueBuildMap.get(code);
            if (valueBuildItem != null){

                //如果楼栋都是不可租售和可租的则不对比
                String mdmBusinessType = mdmBuildItem.getBusinessType();
                String valueBusinessType = valueBuildItem.getBusinessType();
                if ((mdmBusinessType.equals(SalyTypeEnum.RENTED.getKey()) || mdmBusinessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()))
                        && (valueBusinessType.equals(SalyTypeEnum.RENTED.getKey()) || valueBusinessType.equals(SalyTypeEnum.NOT_RENTABLE.getKey()))) {

                    extValueBuildMap.remove(code);
                    continue wc;
                }

                //全部归集的楼栋不对比面积、套数、经营方式、属性标签、装修标准
                Integer isTotalCollect = valueBuildItem.getIsTotalCollect();
                if(isTotalCollect == null || isTotalCollect.equals(IsDeleteEnum.NO.getKey())){

                    //判断楼栋是否全部已供
                    if (isparking){
                        //已售车位数+已定价未售车位数+自持车位数+未推售车位数 ≥ 主数据车位数，即为全部定价
                        Integer parkingSold = valueBuildItem.getParkingSold()==null?0:valueBuildItem.getParkingSold();
                        Integer parkingPriced = valueBuildItem.getParkingPriced()==null?0:valueBuildItem.getParkingPriced();
                        Integer parkingZc = valueBuildItem.getParkingZc()==null?0:valueBuildItem.getParkingZc();
                        Integer forsaleParkingNum = valueBuildItem.getForsaleParkingNum()==null?0:valueBuildItem.getForsaleParkingNum();
                        Integer totalCollectNum = parkingSold + parkingPriced + parkingZc + forsaleParkingNum;

                        Integer mdmRoomNum = mdmBuildItem.getRoomNum()==null?0:mdmBuildItem.getRoomNum();
                        if (totalCollectNum >= mdmRoomNum){

                            extValueBuildMap.remove(code);
                            continue wc;
                        }
                    }else {
                        //已售房源数+已定价未售房源数+自持房源数 ≥ 主数据房源数
                        // 或 已售房源面积+已定价未售房源面积+自持房源面积 ≥ 主数据房源面积  即为全部定价
                        Integer roomSold = valueBuildItem.getRoomSold()==null?0:valueBuildItem.getRoomSold();
                        Integer roomPriced = valueBuildItem.getRoomPriced()==null?0:valueBuildItem.getRoomPriced();
                        Integer roomZc = valueBuildItem.getRoomZc()==null?0:valueBuildItem.getRoomZc();
                        Integer totalCollectNum = roomSold + roomPriced + roomZc;

                        Integer mdmRoomNum = mdmBuildItem.getRoomNum()==null?0:mdmBuildItem.getRoomNum();
                        if (totalCollectNum >= mdmRoomNum){

                            extValueBuildMap.remove(code);
                            continue wc;
                        }

                        BigDecimal areaSold = valueBuildItem.getAreaSold();
                        BigDecimal areaPriced = valueBuildItem.getAreaPriced();
                        BigDecimal areaZc = valueBuildItem.getAreaZc();
                        BigDecimal totalCollectArea = BigDecimalADD(BigDecimalADD(areaSold, areaPriced), areaZc);

                        BigDecimal mdmRoomArea = mdmBuildItem.getTotalSaleArea()==null?new BigDecimal(0):mdmBuildItem.getTotalSaleArea();
                        if (totalCollectArea.compareTo(mdmRoomArea) >= 0){

                            extValueBuildMap.remove(code);
                            continue wc;
                        }
                    }

                    //货值和主数据信息进行比较
                    Integer mdmRoomNum = mdmBuildItem.getRoomNum()==null?0:mdmBuildItem.getRoomNum();
                    if (!mdmRoomNum.equals(valueBuildItem.getNum())){

                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailVOList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                        detailVO.setChangeType(Constants.NUM_CHANGE);
                        Integer subNum = mdmRoomNum - valueBuildItem.getNum();
                        if (subNum > 0) {
                            detailVO.setChangeType(Constants.ADD_NUM_CHANGE + Math.abs(subNum));
                            detailVO.setChangeDetail(valueBuildItem.getNum()+"变为"+mdmRoomNum);
                        } else {
                            detailVO.setChangeType(Constants.REDUCE_NUM_CHANGE + Math.abs(subNum));
                            detailVO.setChangeDetail(valueBuildItem.getNum()+"变为"+mdmRoomNum);
                        }

                        detailVOList.add(detailVO);
                        buildCompareVO.setDetailList(detailVOList);
                    }

                    if (!isparking){
                        BigDecimal mdmRoomArea = mdmBuildItem.getTotalSaleArea()==null?new BigDecimal(0):mdmBuildItem.getTotalSaleArea();
                        if (!mdmRoomArea.equals(valueBuildItem.getSaleArea())){
                            List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                            if (CollectionUtils.isEmpty(detailList)){
                                detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                            }
                            PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                            detailVO.setChangeType(Constants.AREA_CHANGE);
                            BigDecimal subArea = mdmRoomArea.subtract(valueBuildItem.getSaleArea()).setScale(4, BigDecimal.ROUND_HALF_UP);
                            if (subArea.compareTo(new BigDecimal(0)) > 0) {
                                detailVO.setChangeType(Constants.ADD_AREA_CHANGE + subArea.abs());
                                detailVO.setChangeDetail(valueBuildItem.getSaleArea()+"变为"+mdmRoomArea);
                            } else {
                                detailVO.setChangeType(Constants.REDUCE_AREA_CHANGE + subArea.abs());
                                detailVO.setChangeDetail(valueBuildItem.getSaleArea()+"变为"+mdmRoomArea);
                            }

                            detailList.add(detailVO);
                            buildCompareVO.setDetailList(detailList);
                        }
                    }

                    if (!mdmBuildItem.getFreeType().equals(valueBuildItem.getFreeType())){
                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                        if (CollectionUtils.isEmpty(detailList)){
                            detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        }
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                        detailVO.setChangeType(Constants.FREE_TYPE_CHANGE);
                        detailVO.setChangeDetail(valueBuildItem.getFreeTypeName()+"变为"+mdmBuildItem.getFreeTypeName());

                        detailList.add(detailVO);
                        buildCompareVO.setDetailList(detailList);
                    }

                    if (!mdmBuildItem.getBusinessType().equals(valueBuildItem.getBusinessType())){
                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                        if (CollectionUtils.isEmpty(detailList)){
                            detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        }
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                        detailVO.setChangeType(Constants.BUSINESS_TYPE_CHANGE);
                        detailVO.setChangeDetail(valueBuildItem.getBusinessTypeName()+"变为"+mdmBuildItem.getBusinessTypeName());

                        detailList.add(detailVO);
                        buildCompareVO.setDetailList(detailList);
                    }

                    if (!mdmBuildItem.getProType().equals(valueBuildItem.getProType())){
                        List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                        if (CollectionUtils.isEmpty(detailList)){
                            detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                        }
                        PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();
                        detailVO.setChangeType(Constants.PRO_TYPE_CHANGE);
                        detailVO.setChangeDetail(valueBuildItem.getProTypeName()+"变为"+mdmBuildItem.getProTypeName());

                        detailList.add(detailVO);
                        buildCompareVO.setDetailList(detailList);
                    }

                    List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                    if(CollectionUtils.isNotEmpty(detailList)){

                        buildCompareVO.setChangeBeforeNum(valueBuildItem.getNum());
                        buildCompareVO.setChangeBeforeArea(valueBuildItem.getSaleArea());

                        buildCompareVO.setChangeAfterNum(mdmBuildItem.getRoomNum());
                        buildCompareVO.setChangeAfterArea(mdmBuildItem.getTotalSaleArea());

                        buildCompareVOList.add(buildCompareVO);
                    }
                }
            }else{

                //不对比 不可租售 和 可租
                if (mdmBuildItem.getBusinessType().equals(SalyTypeEnum.SALABLE.getKey()) || mdmBuildItem.getBusinessType().equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey())) {
                    List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                    if (CollectionUtils.isEmpty(detailList)){
                        detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                    }
                    PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();

                    detailVO.setChangeType(Constants.UPDATE_BUILD_TYPE);
                    detailVO.setChangeDetail(Constants.UPDATE_BUILD_DETAIL + "增加了楼栋"+mdmBuildItem.getFormatBuildingName());

                    buildCompareVO.setChangeAfterNum(mdmBuildItem.getRoomNum());
                    buildCompareVO.setChangeAfterArea(mdmBuildItem.getTotalSaleArea());

                    detailList.add(detailVO);
                    buildCompareVO.setDetailList(detailList);

                    buildCompareVOList.add(buildCompareVO);
                }
            }

            extValueBuildMap.remove(code);
        }

        if (CollectionUtils.isNotEmpty(extValueBuildMap)){
            for (Map.Entry<String, PriceValueCastDecisionAllOrgEXTBO> extboMap : extValueBuildMap.entrySet()){
                PriceValueCastDecisionAllOrgEXTBO value = extboMap.getValue();

                //不对比 不可租售 和 可租
                if (!value.getBusinessType().equals(SalyTypeEnum.RENTED.getKey()) && !value.getBusinessType().equals(SalyTypeEnum.NOT_RENTABLE.getKey())) {
                    PriceValueCompareVO buildCompareVO = new PriceValueCompareVO();

                    buildCompareVO.setId(UUIDUtils.create());
                    buildCompareVO.setType(OrgTypeEunm.ORG_BUILD.getKey());
                    buildCompareVO.setName(value.getOrgName());
                    buildCompareVO.setCode(value.getCode());

                    //是否车位楼栋
                    boolean isparking = isParkList.contains(value.getProductCode());
                    if (isparking){
                        buildCompareVO.setIsParking(IsDeleteEnum.YES.getKey());
                    }else {
                        buildCompareVO.setIsParking(IsDeleteEnum.NO.getKey());
                    }

                    List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = buildCompareVO.getDetailList();
                    if (CollectionUtils.isEmpty(detailList)){
                        detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                    }
                    PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();

                    detailVO.setChangeType(Constants.UPDATE_BUILD_TYPE);
                    detailVO.setChangeDetail(Constants.UPDATE_BUILD_DETAIL + "删除了楼栋"+value.getOrgName());

                    buildCompareVO.setChangeBeforeArea(value.getSaleArea());
                    buildCompareVO.setChangeBeforeNum(value.getNum());

                    detailList.add(detailVO);
                    buildCompareVO.setDetailList(detailList);

                    buildCompareVOList.add(buildCompareVO);
                }
            }
        }

        //查询货值产品构成数据
        Map<String, PriceValueCastDecisionAllOrgEXTBO> extValueProductMap = new HashMap<String, PriceValueCastDecisionAllOrgEXTBO>();
        List<PriceValueCastDecisionAllOrgEXTBO> newestProductList = priceValueOrgMapper.selectWPProductOrgByVersionId(newestPriceVersion.getId(), IsDeleteEnum.NO.getKey());
        if (CollectionUtils.isNotEmpty(newestProductList)){
            for (PriceValueCastDecisionAllOrgEXTBO extProduct : newestProductList) {
                extValueProductMap.put(extProduct.getCode()+"&"+extProduct.getProductCode(), extProduct);
            }
        }

        //变更主数据产品构成层级
        Map<String, MdmBuildAreaDetailBO> mdmProductMap = new HashMap<String, MdmBuildAreaDetailBO>();
        List<MdmBuildAreaDetailBO> mdmProductItems = mdmProductWarPlanBO.getProductItems();
        for (MdmBuildAreaDetailBO mdmProductItem : mdmProductItems){
            mdmProductMap.put(mdmProductItem.getGroupId()+"&"+mdmProductItem.getProductCode(), mdmProductItem);
        }

        //比较主数据产品构成信息和货值产品构成信息是否一致
        Map<String, PriceValueCompareVO> productCompareMap = new HashMap<String, PriceValueCompareVO>();
        for (PriceValueCompareVO buildVo : buildCompareVOList){
            String code = buildVo.getCode();

            PriceValueOrg productOrg = extValueProductMap.get(code);
            MdmBuildAreaDetailBO mdmProduct = mdmProductMap.get(code);

            PriceValueCompareVO productCompareVO = productCompareMap.get(code);
            String productCompareId = "";
            if (productCompareVO != null){
                productCompareId = productCompareVO.getId();
            }else{
                productCompareVO = new PriceValueCompareVO();
                productCompareId = UUIDUtils.create();
                productCompareVO.setId(productCompareId);
                productCompareVO.setType(OrgTypeEunm.ORG_BUILD.getKey());
            }

            String[] codeSplit = code.split("&");
            String groupCode = codeSplit[0];

            //保存build
            buildVo.setPid(productCompareId);
            resultList.add(buildVo);

            List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = productCompareVO.getDetailList();
            if (CollectionUtils.isEmpty(detailList)) {
                detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
            }
            PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();

            if (productOrg != null) {
                productCompareVO.setName(productOrg.getOrgName());
                productCompareVO.setCode(groupCode);
                detailVO.setChangeDetail(Constants.UPDATE_PRODUCT_DETAIL + productOrg.getOrgName());
            } else {
                productCompareVO.setName(mdmProduct.getProductType());
                productCompareVO.setCode(mdmProduct.getGroupId());
                detailVO.setChangeDetail(Constants.UPDATE_PRODUCT_DETAIL + mdmProduct.getProductType());
            }
            detailVO.setChangeType(Constants.UPDATE_PRODUCT_TYPE);
            detailList.add(detailVO);
            productCompareVO.setDetailList(detailList);

            productCompareVO.setChangeBeforeNum((productCompareVO.getChangeBeforeNum()==null?0:productCompareVO.getChangeBeforeNum()) + (buildVo.getChangeBeforeNum()==null?0:buildVo.getChangeBeforeNum()));
            productCompareVO.setChangeBeforeArea(BigDecimalADD(productCompareVO.getChangeBeforeArea(), buildVo.getChangeBeforeArea()));
            productCompareVO.setChangeAfterNum((productCompareVO.getChangeAfterNum()==null?0:productCompareVO.getChangeAfterNum()) + (buildVo.getChangeAfterNum()==null?0:buildVo.getChangeAfterNum()));
            productCompareVO.setChangeAfterArea(BigDecimalADD(productCompareVO.getChangeAfterArea(), buildVo.getChangeAfterArea()));

            productCompareMap.put(code, productCompareVO);
        }

        //查询货值组团信息
        Map<String, PriceValueOrg> valueGroupMap = new HashMap<String, PriceValueOrg>();
        QueryWrapper<PriceValueOrg> groupWrapper = new QueryWrapper<PriceValueOrg>();
        groupWrapper.eq("version_id",  newestPriceVersion.getId())
                .eq("type", OrgTypeEunm.ORG_GROUP.getKey())
                .eq("is_delete", IsDeleteEnum.NO.getKey());
        List<PriceValueOrg> groupOrgs = priceValueOrgMapper.selectList(groupWrapper);
        for (PriceValueOrg groupItem : groupOrgs){
            valueGroupMap.put(groupItem.getOrgId(), groupItem);
        }

        //变更主数据组团层级
        Map<String, MdmBuildAreaDetailBO> mdmGroupMap = new HashMap<String, MdmBuildAreaDetailBO>();
        List<MdmBuildAreaDetailBO> mdmGroupItems = mdmProductWarPlanBO.getGroupItems();
        for (MdmBuildAreaDetailBO mdmGroupItem : mdmGroupItems){
            mdmGroupMap.put(mdmGroupItem.getGroupId(), mdmGroupItem);
        }

        Map<String, PriceValueCompareVO> groupMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(productCompareMap)) {
            for (Map.Entry<String, PriceValueCompareVO> productComMap : productCompareMap.entrySet()) {

                PriceValueCompareVO productVo = productComMap.getValue();
                String code = productVo.getCode();

                PriceValueOrg valueGroupOrg = valueGroupMap.get(code);
                MdmBuildAreaDetailBO mdmGroup = mdmGroupMap.get(code);
                PriceValueCompareVO compareGroupOrg = groupMap.get(code);
                String groupComId = "";
                if (compareGroupOrg != null) {
                    groupComId = compareGroupOrg.getId();
                } else {
                    compareGroupOrg = new PriceValueCompareVO();
                    groupComId = UUIDUtils.create();
                    compareGroupOrg.setId(groupComId);
                    compareGroupOrg.setType(OrgTypeEunm.ORG_GROUP.getKey());
                }

                //保存product
                productVo.setPid(groupComId);
                resultList.add(productVo);
                compareGroupOrg.setType(OrgTypeEunm.ORG_GROUP.getKey());

                List<PriceValueCompareVO.PriceValueCompareDetailVO> detailList = compareGroupOrg.getDetailList();
                if (CollectionUtils.isEmpty(detailList)) {
                    detailList = new ArrayList<PriceValueCompareVO.PriceValueCompareDetailVO>();
                }
                PriceValueCompareVO.PriceValueCompareDetailVO detailVO = new PriceValueCompareVO.PriceValueCompareDetailVO();

                if (valueGroupOrg != null) {
                    compareGroupOrg.setName(valueGroupOrg.getOrgName());
                    compareGroupOrg.setCode(valueGroupOrg.getOrgId());
                    detailVO.setChangeDetail(Constants.UPDATE_GROUP_DETAIL + valueGroupOrg.getOrgName());
                } else {
                    compareGroupOrg.setName(mdmGroup.getGroupName());
                    compareGroupOrg.setCode(mdmGroup.getGroupId());
                    detailVO.setChangeDetail(Constants.UPDATE_GROUP_DETAIL + mdmGroup.getGroupName());
                }
                detailVO.setChangeType(Constants.UPDATE_GROUP_TYPE);
                detailList.add(detailVO);
                compareGroupOrg.setDetailList(detailList);

                compareGroupOrg.setChangeBeforeNum((compareGroupOrg.getChangeBeforeNum()==null?0:compareGroupOrg.getChangeBeforeNum()) + (productVo.getChangeBeforeNum()==null?0:productVo.getChangeBeforeNum()));
                compareGroupOrg.setChangeBeforeArea(BigDecimalADD(compareGroupOrg.getChangeBeforeArea(), productVo.getChangeBeforeArea()));
                compareGroupOrg.setChangeAfterNum((compareGroupOrg.getChangeAfterNum()==null?0:compareGroupOrg.getChangeAfterNum()) + (productVo.getChangeAfterNum()==null?0:productVo.getChangeAfterNum()));
                compareGroupOrg.setChangeAfterArea(BigDecimalADD(compareGroupOrg.getChangeAfterArea(), productVo.getChangeAfterArea()));

                groupMap.put(code, compareGroupOrg);
            }
        }

        //分期信息
        PriceValueCompareVO compareProjectfVOOrg = null;
        if (CollectionUtils.isNotEmpty(groupMap)) {
            for (Map.Entry<String, PriceValueCompareVO> groupComMap : groupMap.entrySet()) {

                PriceValueCompareVO groupValue = groupComMap.getValue();

                String pfId = "";
                if (compareProjectfVOOrg != null) {
                    pfId = compareProjectfVOOrg.getId();
                }else{
                    compareProjectfVOOrg = new PriceValueCompareVO();
                    pfId = UUIDUtils.create();
                }

                //保存group
                groupValue.setPid(pfId);
                resultList.add(groupValue);
                compareProjectfVOOrg.setType(OrgTypeEunm.ORG_STAGE.getKey());

                compareProjectfVOOrg.setId(pfId);
                compareProjectfVOOrg.setPid("0");
                compareProjectfVOOrg.setName(mdmProductWarPlanBO.getProjectFItems().getProjectName() + " " + mdmProductWarPlanBO.getProjectFItems().getStageName());
                compareProjectfVOOrg.setType(OrgTypeEunm.ORG_STAGE.getKey());

                compareProjectfVOOrg.setChangeBeforeNum((compareProjectfVOOrg.getChangeBeforeNum()==null?0:compareProjectfVOOrg.getChangeBeforeNum()) + (groupValue.getChangeBeforeNum()==null?0:groupValue.getChangeBeforeNum()));
                compareProjectfVOOrg.setChangeBeforeArea(BigDecimalADD(compareProjectfVOOrg.getChangeBeforeArea(), groupValue.getChangeBeforeArea()));
                compareProjectfVOOrg.setChangeAfterNum((compareProjectfVOOrg.getChangeAfterNum()==null?0:compareProjectfVOOrg.getChangeAfterNum()) + (groupValue.getChangeAfterNum()==null?0:groupValue.getChangeAfterNum()));
                compareProjectfVOOrg.setChangeAfterArea(BigDecimalADD(compareProjectfVOOrg.getChangeAfterArea(), groupValue.getChangeAfterArea()));
            }
        }

        if(compareProjectfVOOrg != null){
            resultList.add(compareProjectfVOOrg);
            noticePriceCompareVo.setCompareVOS(resultList);
        }else{
            noticePriceCompareVo.setCompareMsg(CodeEnum.NON_COMPARRE_ERROR.getMessage());
            return noticePriceCompareVo;
        }

        return noticePriceCompareVo;
    }

    /**
     *  自动创建战规后指定楼栋计划和楼栋业态面积货值版本
     * @param projectFid 分期id
     * @param appointPriceVersion 指定货值版本
     * @param isFinalization 是否定稿
     * @param ascriptionDate 归属日期
     * @param remake 备注信息
     * @param lable 创建类型
     * @param instId esb报文instId
     * @return 版本id
     */
    @Override
    public synchronized String createSysAppointDynamicVersion(String projectFid, PriceVersion appointPriceVersion, Integer isFinalization, LocalDate ascriptionDate, String remake, Integer lable, String instId, String source) {
        LocalDateTime now = LocalDateTime.now();
        String projectfId = appointPriceVersion.getProjectfId();
        //查询指定分期信息
        MdmStage mdmStage = getMdmStageByStageId(projectFid);
        //查询指定货值版本中引用主数据信息
        String sourceAreaVersionStage = appointPriceVersion.getSourceAreaVersionStage();
        String sourceAreaVersionNum = appointPriceVersion.getSourceAreaVersionNum();
        LocalDateTime sourceAreaSysCreatedTime = appointPriceVersion.getSourceAreaSysCreatedTime();
        String sourceGroupVersionStage = appointPriceVersion.getSourceGroupVersionStage();
        String sourceGroupVersionCode = appointPriceVersion.getSourceGroupVersionCode();
        LocalDateTime sourceGroupCreateTime = appointPriceVersion.getSourceGroupCreateTime();

        //查询指定主数据信息
        MdmBuildAreaBO mdmProductWarPlanBO = buildAreaService.selectAppoint(projectfId, sourceAreaVersionStage, sourceAreaVersionNum, sourceAreaSysCreatedTime,
                sourceGroupVersionStage, sourceGroupVersionCode, sourceGroupCreateTime);
        if(mdmProductWarPlanBO == null){
            throw new MsgException(CodeEnum.NON_APPOINT_GROUPBLD_AREA);
        }

        //查询指定货值版本中引用楼栋计划信息
        String sourcePlan = appointPriceVersion.getSourcePlan();

        //获取最新的战规版楼栋计划
        PanoPlanCastDecisionBO panoPlanCastDecisionBO = panoplanBuildPlanService.selectById(sourcePlan);

        //全景计划系统最新版楼栋计划项目树与主数据系统最新版面积版本项目树不匹配，不允许创建新版本；
        mdmToPanoGroupVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO);

        mdmToPanoProductVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO);

        Map<String, String> panoplanBuildPlanItemMap = new HashMap<>();
        Map<String, PanoplanBuildPlanItem> panoplanItemMap = new HashMap<>();
        mdmToPanoBuildVerification(panoPlanCastDecisionBO, mdmProductWarPlanBO, panoplanBuildPlanItemMap, panoplanItemMap);

        //楼栋计划匹配节点
        Map<String, LocalDateTime> openTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> advanceSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> supplyTimeVirtualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> openSaleTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> cappingTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> completedTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> carryOverTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> actualDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeMap = new HashMap<String, LocalDateTime>();
        Map<String, LocalDateTime> contractDeliveryTimeActualMap = new HashMap<String, LocalDateTime>();
        panoTimeItemNodeMapInfo(panoPlanCastDecisionBO, panoplanBuildPlanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap);

        //分期有可售或阶段性自持产品构成没有批次或供货日期时，不允许新建该分期价格版本
        buildBusinessTypeVerificationByNode(panoPlanCastDecisionBO, panoplanBuildPlanItemMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap);

        //查询取数系统
        String fetchSysId = appointPriceVersion.getCountingSystemId();
        String fetchSysCode = appointPriceVersion.getCountingSystemCode();

        LocalDateTime fetchTime = appointPriceVersion.getCountingTime();

        //项目操盘方式
        String market = appointPriceVersion.getIsMarket();

        //查询本月审批通过和自动生成动态版的版本信息
        String oldVersionId = "";
        String oldVersionNum = "";
        PriceVersion priceVersion = priceVersionService.selectNewestVersionByFidAndDate(projectFid, Arrays.asList(VersionTypeEunm.DYNAMIC.getKey()), Arrays.asList(VersionStatusEnum.SUCCESSAPPROVED.getKey(), VersionStatusEnum.SYSGENERATION.getKey()), IsDeleteEnum.NO.getKey(), now);
        if(priceVersion != null){
            if (priceVersion.getVersionType().equals(VersionTypeEunm.DYNAMIC.getKey())){
                LocalDate preAscriptionDate = priceVersion.getAscriptionDate();
                if(preAscriptionDate != null){
                    Month preMonth = preAscriptionDate.getMonth();
                    Month month = ascriptionDate.getMonth();
                    if(preMonth.equals(month)){
                        oldVersionId = priceVersion.getId();
                        oldVersionNum = priceVersion.getVersionNum();
                    }
                }
            }else{
                oldVersionId = priceVersion.getId();
                oldVersionNum = priceVersion.getVersionNum();
            }
        }

        //查询全盘最新货值（复制战规后最新货值版本）
        String sourceValueId = "";
        Map<String, PriceValueOrg> presaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已售车位
        Map<String, PriceValueOrg> prenotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版已定价未售车位
        Map<String, PriceValueOrg> preSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版可售车位
        Map<String, PriceValueOrg> preNotSaleParkMap = new HashMap<String, PriceValueOrg>(); //上一版未推售车位
        Map<String, List<PriceValueOrg>> preHouseMap = new HashMap<String, List<PriceValueOrg>>(); //上一版房源包
        Map<String, PriceValueOrg> preBuildMap = new HashMap<String, PriceValueOrg>(); //上一版楼栋
        Map<String, BigDecimal> preBuildAvPriceMap = new HashMap<String, BigDecimal>();//上一版楼栋均价
        PriceVersion newestPriceVersion = priceVersionService.getNewestPriceVersion(mdmStage.getProjectFid());
        if(newestPriceVersion != null){
            sourceValueId = dynamicVersionPreOrgInfo(sourceValueId, presaleParkMap, prenotSaleParkMap, preSaleParkMap, preNotSaleParkMap, preHouseMap, preBuildMap, preBuildAvPriceMap, newestPriceVersion);
        }

        //创建新版本
        PriceVersion newVersion = createVersionInfo(projectFid, VersionTypeEunm.DYNAMIC.getKey(), VersionCreateEnum.AUTOMATICCREATE.getKey(), Constants.SYS, mdmStage, ascriptionDate, oldVersionId, oldVersionNum, lable,
                mdmProductWarPlanBO, panoPlanCastDecisionBO, isFinalization, sourceValueId, fetchTime, fetchSysCode, fetchSysId, market, now,WhetherEnum.NO.getKey());

        //创建分期
        PriceValueOrg projectOrg = createStageValueInfo(now, mdmStage, newVersion.getId());

        //创建组团
        Map<String, PriceValueOrg> groupMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> groupInsertMap = new HashMap<String, PriceValueOrg>();
        List<MdmBuildAreaDetailBO> groupItems = mdmProductWarPlanBO.getGroupItems();
        for(MdmBuildAreaDetailBO groupItem : groupItems) {
            dynamicVersionGroupItemInfo(now, newVersion, projectOrg, groupMap, groupInsertMap, groupItem);
        }

        //创建产品构成
        Map<String, PriceValueOrg> productMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> productInsertMap = new HashMap<String, PriceValueOrg>();
        List<MdmBuildAreaDetailBO> productItems = mdmProductWarPlanBO.getProductItems();

        //寻找上级分类
        dynamicVersionProductToDic(now, newVersion, groupMap, productMap, productInsertMap, productItems);

        //创建楼栋
        List<String> parkingBuildList = new ArrayList<>();
        List<PriceValueOrg> buildList = new ArrayList<PriceValueOrg>();
        for(MdmBuildAreaDetailBO buildItem : mdmProductWarPlanBO.getBuildItems()){
            PriceValueOrg buildOrg = createBuildValueInfo(now, panoplanItemMap, openTimeMap, openTimeActualMap, advanceSaleTimeMap, advanceSaleTimeActualMap, supplyTimeMap, supplyTimeActualMap, supplyTimeVirtualMap, openSaleTimeMap, openSaleTimeActualMap, cappingTimeMap, cappingTimeActualMap, completedTimeMap, completedTimeActualMap, carryOverTimeMap, carryOverTimeActualMap, actualDeliveryTimeMap, actualDeliveryTimeActualMap, contractDeliveryTimeMap, contractDeliveryTimeActualMap, newVersion.getId(), productMap, parkingBuildList, buildItem);

            buildList.add(buildOrg);
        }

        //查看取数系统
        Map<String, PriceValueOrg> soldParkingMap = new HashMap<String, PriceValueOrg>();
        Map<String, PriceValueOrg> notSoldParkingOrgMap = new HashMap<String, PriceValueOrg>();
        Map<String, Map<String ,PriceValueOrg>> houseOrgMap = new HashMap<String, Map<String ,PriceValueOrg>>();
        Map<String, BigDecimal> areaMap = new HashMap<>();
        Map<String, Integer> numMap = new HashMap<>();

        //自持信息
        Map<String, Integer> zcParkingNumMap = new HashMap<>();//楼栋下自持房源套数
        Map<String, BigDecimal> zcParkingPriceMap = new HashMap<>();//楼栋下自持房源面积

        //收集面积段
        if (fetchSysCode.equals(FetchNnumberEnum.MY.getKey())){
        	//TODO 明源签约数据改成ESB下发，生产上线此处projectFid应改成 mdmStage.getKingdeeProjectfId()
            Map<String, Map> houseParkMap = myCollectHouse(projectFid,mdmStage.getKingdeeProjectfId(), parkingBuildList, preBuildAvPriceMap, now,null);
            soldParkingMap = houseParkMap.get("soldParkingMap");
            notSoldParkingOrgMap = houseParkMap.get("notSoldParkingOrgMap");
            houseOrgMap = houseParkMap.get("houseOrgMap");
            areaMap = houseParkMap.get("areaMap");
            numMap = houseParkMap.get("numMap");

            zcParkingNumMap = houseParkMap.get("zcParkingNumMap");
            zcParkingPriceMap = houseParkMap.get("zcParkingPriceMap");
        }else if(fetchSysCode.equals(FetchNnumberEnum.NOS.getKey())){
            Map<String, Map> houseParkMap = nosCollectHouse(mdmStage.getKingdeeProjectfId(), now,null);
            soldParkingMap = houseParkMap.get("soldParkingMap");
            houseOrgMap = houseParkMap.get("houseOrgMap");
            areaMap = houseParkMap.get("areaMap");
            numMap = houseParkMap.get("numMap");
        }

        //是否有销售货值
        if (CollectionUtils.isNotEmpty(houseOrgMap) || CollectionUtils.isNotEmpty(soldParkingMap) || CollectionUtils.isNotEmpty(notSoldParkingOrgMap)){
            newVersion.setIsContainSale(IsDeleteEnum.YES.getKey());
        }else{
            newVersion.setIsContainSale(IsDeleteEnum.NO.getKey());
        }

        List<PriceValueOrg> buildInsertList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> hoseSoleList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> sortParkList = new ArrayList<PriceValueOrg>();

        //赋值楼栋货值
        for (PriceValueOrg buildOrg : buildList){
            dynamicVersionBuildToOtherItemInfo(now, fetchSysCode, preSaleParkMap, preHouseMap, preBuildMap, newVersion, soldParkingMap, notSoldParkingOrgMap, houseOrgMap, areaMap, numMap, zcParkingNumMap, zcParkingPriceMap, buildInsertList, hoseSoleList, sortParkList, buildOrg);
        }

        //货值汇总
        List<PriceValueOrg> groupInsertList = new ArrayList<PriceValueOrg>();
        List<PriceValueOrg> productInsertList = new ArrayList<PriceValueOrg>();
        if (CollectionUtils.isNotEmpty(buildInsertList)) {
            dynamicVersionSumInfo(projectOrg, groupInsertMap, productInsertMap, buildInsertList, groupInsertList, productInsertList);
        }
        List<PriceValueOrg> projectList = Arrays.asList(projectOrg);

        //保存
        priceVersionService.saveInfo(newVersion,projectList,groupInsertList,productInsertList,buildInsertList,hoseSoleList,sortParkList);

        //修改添加代办消息
        priceCreateNoticeInfo(instId, source, now, newVersion);

        try{
            versionLogService.saveVersionLogInfo(newVersion.getProjectId(), newVersion.getProjectfId(), ModuleTypeEunm.PRICE.getKey(), VersionEventEnum.SYS_GENERATE.getKey(), newVersion.getId(), VersionNameUtils.getVersionName(newVersion), null,
                    newVersion.getVersionState(), "1", instId, Constants.SYS, now, "货值复制创建版本", null, IsDeleteEnum.NO.getKey(), Constants.SYS, now);
        }catch (Exception e){
            logger.error("################ refresh price version versionLog error : "+e);
        }

        return newVersion.getId();
    }

    protected void dynamicVersionSumInfo(PriceValueOrg projectOrg, Map<String, PriceValueOrg> groupInsertMap, Map<String, PriceValueOrg> productInsertMap, List<PriceValueOrg> buildInsertList, List<PriceValueOrg> groupInsertList, List<PriceValueOrg> productInsertList) {
        for (PriceValueOrg buildOrg : buildInsertList) {
            String pid = buildOrg.getPid();
            PriceValueOrg valueOrg = productInsertMap.get(pid);
            if (valueOrg != null) {
                valueUpSummary(valueOrg, buildOrg);

                productInsertMap.put(pid, valueOrg);
            }
        }

        for (Map.Entry<String, PriceValueOrg> pruductMap : productInsertMap.entrySet()) {
            PriceValueOrg pruductOrg = pruductMap.getValue();
            String pid = pruductOrg.getPid();
            PriceValueOrg groupOrg = groupInsertMap.get(pid);
            if (groupOrg != null) {

                valueUpSummary(groupOrg, pruductOrg);

                groupInsertMap.put(pid, groupOrg);
            }

            productInsertList.add(pruductOrg);
        }

        for (Map.Entry<String, PriceValueOrg> groupOrgMap : groupInsertMap.entrySet()) {
            PriceValueOrg groupOrg = groupOrgMap.getValue();
            if (groupOrg != null) {

                valueUpSummary(projectOrg, groupOrg);
            }

            groupInsertList.add(groupOrg);
        }
    }

    private void dynamicVersionProductToDic(LocalDateTime now, PriceVersion newVersion, Map<String, PriceValueOrg> groupMap, Map<String, PriceValueOrg> productMap, Map<String, PriceValueOrg> productInsertMap, List<MdmBuildAreaDetailBO> productItems) {
        Map<String, DictionaryCodeBO> dicMap = getProductDictionary(productItems);

        for (MdmBuildAreaDetailBO productItem : productItems) {
            dynamicVersionProductItemInfo(newVersion, now, groupMap, productMap, productInsertMap, dicMap, productItem);
        }
    }

    private void dynamicVersionGroupItemInfo(LocalDateTime now, PriceVersion newVersion, PriceValueOrg projectOrg, Map<String, PriceValueOrg> groupMap, Map<String, PriceValueOrg> groupInsertMap, MdmBuildAreaDetailBO groupItem) {
        PriceValueOrg groupOrg = createGroupValueInfo(now, newVersion.getId(), projectOrg, groupItem);

        groupMap.put(groupItem.getGroupId(), groupOrg);
        groupInsertMap.put(groupOrg.getId(), groupOrg);
    }

    //修改添加代办消息
    private void priceCreateNoticeInfo(String instId, String source, LocalDateTime now, PriceVersion newVersion) {
        try{
            String taskName = "";
            if (StringUtils.isNotEmpty(source) && source.equals(Constants.MY)){
                taskName = Constants.NOTICE_MY_CREATE;
            }else if (StringUtils.isNotEmpty(source) && source.equals(Constants.NOS)){
                taskName = Constants.NOTICE_NOS_CREATE;
            }else if (StringUtils.isNotEmpty(source) && source.equals(Constants.CLICK)){
                taskName = Constants.NOTICE_CLICK_CREATE;
            }else {
                taskName = Constants.NOTICE_DG_CREATE;
            }
            mymRoomInfoServiceImpl.noticeDownsRecordProcessedInfo(taskName, instId, newVersion.getId(), newVersion.getProjectId(), newVersion.getProjectfId(), ProcessingStateEnum.PROCESSED.getKey(), ProcessingModeEnum.SYSTEM.getKey(), source, now);
        }catch (Exception e){
            logger.error("################ 添加代办消息 error :"+e.getMessage(), e);
        }
    }

    //创建org_product层级
    public PriceValueOrg createProductValueInfo(LocalDateTime now, String newVersionId, Map<String, PriceValueOrg> groupMap, Map<String, DictionaryCodeBO> dicMap, MdmBuildAreaDetailBO productItem) {
        PriceValueOrg priceValueOrg = new PriceValueOrg();
        String productId = UUIDUtils.create();
        priceValueOrg.setId(productId);
        priceValueOrg.setVersionId(newVersionId);
        priceValueOrg.setPid(groupMap.get(productItem.getGroupId()).getId());
        priceValueOrg.setType(OrgTypeEunm.ORG_PRODUCT.getKey());
        priceValueOrg.setOrgId("");

        priceValueOrg.setProductCode(productItem.getProductCode());
        priceValueOrg.setProductType(productItem.getProductType());
        DictionaryCodeBO dictionaryCodeBO = dicMap.get(productItem.getProductCode());
        if (dictionaryCodeBO != null) {
            priceValueOrg.setOrgCode(dictionaryCodeBO.getChildCode());
            priceValueOrg.setOrgName(dictionaryCodeBO.getChildName());

            priceValueOrg.setProProductCode(dictionaryCodeBO.getParentCode());
            priceValueOrg.setProProductType(dictionaryCodeBO.getParentName());
        }else{
            priceValueOrg.setOrgCode(productItem.getProductCode());
            priceValueOrg.setOrgName(productItem.getProductType());
        }

        if (isParkList.contains(productItem.getProductCode())) {
            priceValueOrg.setIsParking(IsDeleteEnum.YES.getKey());
        } else {
            priceValueOrg.setIsParking(IsDeleteEnum.NO.getKey());
        }
        priceValueOrg.setIsDelete(IsDeleteEnum.NO.getKey());
        priceValueOrg.setCreateTime(now);
        priceValueOrg.setUpdateTime(now);
        return priceValueOrg;
    }

    //分期有可售或阶段性自持产品构成没有批次或供货日期时，不允许新建该分期价格版本
    public void buildBusinessTypeVerificationByNode(PanoPlanCastDecisionBO panoPlanCastDecisionBO, Map<String, String> panoplanBuildPlanItemMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap) {
        List<PanoplanBuildPlanItem> panoplanBuildPlanItems = panoPlanCastDecisionBO.getBuildItems();
        for (int i = 0; i < panoplanBuildPlanItems.size(); i++) {
            PanoplanBuildPlanItem panoplanBuildPlanItem = panoplanBuildPlanItems.get(i);
            String saleNum = panoplanBuildPlanItem.getSaleNum();
            if (StringUtils.isNotEmpty(saleNum) && (saleNum.equals(SalyTypeEnum.SALABLE.getKey())
                    || saleNum.equals(SalyTypeEnum.STAGE_SELF_SUSTAINMENT.getKey()))) {
                String codes = panoplanBuildPlanItemMap.get(panoplanBuildPlanItem.getId());
                LocalDateTime supplyTime = supplyTimeMap.get(codes);
                LocalDateTime supplyActualTime = supplyTimeActualMap.get(codes);
                LocalDateTime supplyVirtualTime = supplyTimeVirtualMap.get(codes);
                if (supplyTime == null && supplyActualTime == null && supplyVirtualTime == null) {
                    throw new MsgException(CodeEnum.NON_PANO_TIME);
                }
            }
        }
    }

    //楼栋计划时间节点匹配
    public void panoTimeItemNodeMapInfo(PanoPlanCastDecisionBO panoPlanCastDecisionBO, Map<String, String> panoplanBuildPlanItemMap, Map<String, LocalDateTime> openTimeMap, Map<String, LocalDateTime> openTimeActualMap, Map<String, LocalDateTime> advanceSaleTimeMap, Map<String, LocalDateTime> advanceSaleTimeActualMap, Map<String, LocalDateTime> supplyTimeMap, Map<String, LocalDateTime> supplyTimeActualMap, Map<String, LocalDateTime> supplyTimeVirtualMap, Map<String, LocalDateTime> openSaleTimeMap, Map<String, LocalDateTime> openSaleTimeActualMap, Map<String, LocalDateTime> cappingTimeMap, Map<String, LocalDateTime> cappingTimeActualMap, Map<String, LocalDateTime> completedTimeMap, Map<String, LocalDateTime> completedTimeActualMap, Map<String, LocalDateTime> carryOverTimeMap, Map<String, LocalDateTime> carryOverTimeActualMap, Map<String, LocalDateTime> actualDeliveryTimeMap, Map<String, LocalDateTime> actualDeliveryTimeActualMap, Map<String, LocalDateTime> contractDeliveryTimeMap, Map<String, LocalDateTime> contractDeliveryTimeActualMap) {
        if (CollectionUtils.isNotEmpty(panoPlanCastDecisionBO.getDetails())) {
            for (PanoplanBuildPlanItemDetail buildDetailItem : panoPlanCastDecisionBO.getDetails()) {
                String codes = panoplanBuildPlanItemMap.get(buildDetailItem.getPkId());
                if (StringUtils.isNotEmpty(codes)) {
                    String nodeCode = buildDetailItem.getNodeCode();
                    if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00002.getKey())) {
                        openTimeMap.put(codes, buildDetailItem.getPlannedFinishDate());
                        openTimeActualMap.put(codes, buildDetailItem.getActualFinishDate());
                    } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00001.getKey())) {
                        advanceSaleTimeMap.put(codes, buildDetailItem.getPlannedFinishDate());
                        advanceSaleTimeActualMap.put(codes, buildDetailItem.getActualFinishDate());
                    } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00002.getKey())) {
                        supplyTimeMap.put(codes, buildDetailItem.getPlannedFinishDate());
                        supplyTimeActualMap.put(codes, buildDetailItem.getActualFinishDate());
                        supplyTimeVirtualMap.put(codes, buildDetailItem.getVirtualFinishDate());
                    } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00003.getKey())) {
                        openSaleTimeMap.put(codes, buildDetailItem.getPlannedFinishDate());
                        openSaleTimeActualMap.put(codes, buildDetailItem.getActualFinishDate());
                    } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_YJ_00003.getKey())) {
                        cappingTimeMap.put(codes, buildDetailItem.getPlannedFinishDate());
                        cappingTimeActualMap.put(codes, buildDetailItem.getActualFinishDate());
                    } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00004.getKey())) {
                        completedTimeMap.put(codes, buildDetailItem.getPlannedFinishDate());
                        completedTimeActualMap.put(codes, buildDetailItem.getActualFinishDate());
                    } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00006.getKey())) {
                        carryOverTimeMap.put(codes, buildDetailItem.getPlannedFinishDate());
                        carryOverTimeActualMap.put(codes, buildDetailItem.getActualFinishDate());
                    } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.JT_LCB_00005.getKey())) {
                        actualDeliveryTimeMap.put(codes, buildDetailItem.getPlannedFinishDate());
                        actualDeliveryTimeActualMap.put(codes, buildDetailItem.getActualFinishDate());
                    } else if (StringUtils.isNotEmpty(nodeCode) && nodeCode.equals(NodeEnum.NODE_000.getKey())) {
                        contractDeliveryTimeMap.put(codes, buildDetailItem.getPlannedFinishDate());
                        contractDeliveryTimeActualMap.put(codes, buildDetailItem.getActualFinishDate());
                    }
                }
            }
        }
    }

    /**
     *  货值门户代办
     * @param projectId 项目id
     * @param projectFid 分期id
     * @param title 标题
     * @param versionId 版本id
     * @return 门户 instanceId
     */
    @Override
    public String sendBackLog(String projectId, String projectFid, String title, String versionId) {
        List<ProjectByStages> parentList = projectMapper.selectParentData(projectId);
        String groupId = "";
        String businessId="";
        String cityId="";
        String pcUrl = "";
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(parentList)) {
            for(ProjectByStages obj : parentList) {
                String typeId = obj.getHrOrgTypeId();
                if(typeId.equals(HrOrgTypeEunm.ORG_11.getKey())) {
                    groupId = obj.getOrgdepid();
                }else if(typeId.equals(HrOrgTypeEunm.ORG_21.getKey())) {
                    cityId = obj.getOrgdepid();
                }else if(typeId.equals(HrOrgTypeEunm.ORG_20.getKey())) {
                    businessId = obj.getOrgdepid();
                }
            }
        }

        if (StringUtils.isEmpty(businessId) || StringUtils.isEmpty(cityId) || StringUtils.isEmpty(projectId)){
            return null;
        }

        pcUrl = priceNoticePcUrl+businessId+"/"+cityId+"/"+projectId;

        //项目PM
        List<IdmUser> userList = getProjectPm(projectId);
        PortalTodoBo doorTodoBo=new PortalTodoBo();
        //移动端地址，钉钉上收到待办时，点击后进入的地址。（可为钉钉应用首页）必传
        doorTodoBo.setMobileTaskUrl(priceNoticeAppUrl);
        //PC端地址，门户portal.cifi.com.cn中点击一条待办后进入的地址。必传
        doorTodoBo.setPcTaskUrl(pcUrl);
        //待办的主题 自己定义
        doorTodoBo.setTitle(title);
        doorTodoBo.setContent(title);
        //任务类型，待办列表中显示在主题前面的中括号中，表示提醒审批人待审批的是什么。如“转交”，“驳回”，“合同审批”等，最多用四个字来总结
        doorTodoBo.setTodoType(TodoTypeCodeEnum.PRICE_VALUE.getValue());
        //任务类型code
        doorTodoBo.setTodoTypeCode(TodoTypeCodeEnum.PRICE_VALUE.getKey());
        // 任务关联id
        doorTodoBo.setVersionId(versionId);
        //任务关联id类型
        doorTodoBo.setVersionIdType(VersionIdTypeEnum.PRICE_VALUE.getKey());
        //待办组织类型
        doorTodoBo.setOrgType(TodoOrgTypeEnum.FIVE.getKey());
        //处理时间
        //doorTodoBo.setHandleTime(LocalDateTime.now());
        //集团id
        doorTodoBo.setGroupId(groupId);
        //区域或事业部id
        doorTodoBo.setRegionId(businessId);
        //城市公司id
        doorTodoBo.setCityId(cityId);
        //项目id
        doorTodoBo.setProjectId(projectId);
        //分期id
        doorTodoBo.setStagesId(projectFid);
        return commonService.start("", doorTodoBo, userList);
    }

    //获取项目营销PM
    private List<IdmUser> getProjectPm(String projectId) {
        List<IdmUser> userList = Collections.synchronizedList(new ArrayList<>());
        HashSet<GroupUserVo> set = idmUserService.getGroupUserInfo(Constants.PROJECT_MARKETING_PM,projectId);
        if(org.apache.commons.collections.CollectionUtils.isNotEmpty(set)) {
            for(GroupUserVo vo : set) {
                IdmUser user = idmUserService.getByAlias(vo.getAlias());
                userList.add(user);
            }
        }
        return userList;
    }

    /**
     * 分期下全盘最新版本刷新实际数据
     * @param projectFid
     */
    @Override
    public void refreshPriceValueByStageId(String projectFid) {
        //刷新货值信息
        Thread refreshPriceVersionByStageId = new RefreshPriceVersionByStageId(projectFid, LocalDateTime.now());
        refreshPriceVersionByStageId.start();
    }

    class RefreshPriceVersionByStageId extends Thread {
        private String projectFid;
        private LocalDateTime now;

        public RefreshPriceVersionByStageId(String projectFid, LocalDateTime now) {
            this.projectFid = projectFid;
            this.now = now;
        }

        public void run() {
            try{
                //归属年月
                LocalDate ascriptionDate = LocalDate.now();
                int day = now.getDayOfMonth();
                int hour = now.getHour();
                if (day == Constants.ONE && hour <=  Constants.SIX){//一号
                    ascriptionDate = ascriptionDate.minusMonths(1);
                }

                //查询货值版本，如果没有动态版本，则不处理，剩余分期直接刷新和生成新版本
                if (StringUtils.isNotEmpty(projectFid)) {
                    PriceVersion priceVersion = priceVersionServiceImpl.getNewestPriceVersionAllVersionState(projectFid);
                    if (priceVersion != null) {
                        String versionType = priceVersion.getVersionType();
                        if (versionType.equals(VersionTypeEunm.DYNAMIC.getKey())){
                            String versionState = priceVersion.getVersionState();
                            if (versionState.equals(VersionStatusEnum.NOTPREPARED.getKey()) || versionState.equals(VersionStatusEnum.ORGANIZATION.getKey())
                                    || versionState.equals(VersionStatusEnum.EXAMINEDAPPROVED.getKey()) || versionState.equals(VersionStatusEnum.FAILUREAPPROVED.getKey())){
                                priceRefreshActualValueInfo(projectFid, priceVersion, null, null,LocalDateTime.now(), Constants.CLICK, null);
                            }else if (versionState.equals(VersionStatusEnum.SUCCESSAPPROVED.getKey())){
                                try {
                                    String versionId = createSysAppointDynamicVersion(priceVersion.getProjectfId(), priceVersion, null, ascriptionDate, "实际数据刷新生成", 3, null, Constants.CLICK);

                                    supplyPlanVersionService.createSupplyPlanVersion(versionId, VersionTypeEunm.DYNAMIC.getKey(), Constants.SYS);
                                } catch (Exception e) {
                                    logger.error("###################     RefreshPriceVersionByMymRooms    SUCCESSAPPROVED   货值自动生成:"+e.getMessage(), e);
                                }
                            }else if (versionState.equals(VersionStatusEnum.SYSGENERATION.getKey())){

                                //查看货值版本是否有被供货确认使用
                                boolean isComfirm = supplyPlanVersionService.supplyIsComfirm(priceVersion.getId());

                                if (isComfirm){
                                    try {
                                        String versionId = createSysAppointDynamicVersion(priceVersion.getProjectfId(), priceVersion, null, ascriptionDate, "实际数据刷新生成", 3, null, Constants.CLICK);

                                        supplyPlanVersionService.createSupplyPlanVersion(versionId, VersionTypeEunm.DYNAMIC.getKey(), Constants.SYS);
                                    } catch (Exception e) {
                                        logger.error("###################    RefreshPriceVersionByMymRooms  货值自动生成:"+e.getMessage(), e);
                                    }
                                }else{
                                    //查看货值版本是否有被签约使用
                                    Map<String, Boolean> signMap = signPlanVersionService.priceBoolean(Arrays.asList(priceVersion.getId()));
                                    Boolean isSign = signMap.get(priceVersion.getId());

                                    if (isSign){
                                        try {
                                            String versionId = createSysAppointDynamicVersion(priceVersion.getProjectfId(), priceVersion, null, ascriptionDate, "实际数据刷新生成", 3, null, Constants.CLICK);

                                            supplyPlanVersionService.createSupplyPlanVersion(versionId, VersionTypeEunm.DYNAMIC.getKey(), Constants.SYS);
                                        } catch (Exception e) {
                                            logger.error("###################    RefreshPriceVersionByMymRooms   货值自动生成:"+e.getMessage(), e);
                                        }
                                    }else{
                                        //查看货值版本是否有定稿
                                        Integer isFinalization = priceVersion.getIsFinalization();

                                        if (isFinalization != null && isFinalization.equals(IsDeleteEnum.YES.getKey())){
                                            try {
                                                String versionId = createSysAppointDynamicVersion(priceVersion.getProjectfId(), priceVersion, null, ascriptionDate, "实际数据刷新生成", 3, null, Constants.CLICK);

                                                supplyPlanVersionService.createSupplyPlanVersion(versionId, VersionTypeEunm.DYNAMIC.getKey(), Constants.SYS);
                                            } catch (Exception e) {
                                                logger.error("###################    RefreshPriceVersionByMymRooms   货值自动生成:"+e.getMessage(), e);
                                            }
                                        }else{
                                            Map<String, String> resultVersionIdAndVersionTypeMap = new HashMap<String, String>();
                                            try{
                                                resultVersionIdAndVersionTypeMap = priceRefreshActualValueInfo(projectFid, priceVersion, null, null,LocalDateTime.now(), Constants.CLICK , null);
                                            }catch (Exception e){
                                                logger.error("###################    RefreshPriceVersionByMymRooms    货值自动生成:"+e.getMessage(), e);
                                            }

                                            if (CollectionUtils.isNotEmpty(resultVersionIdAndVersionTypeMap)){
                                                for (Map.Entry<String, String> resultmap : resultVersionIdAndVersionTypeMap.entrySet()){
                                                    try {
                                                        supplyPlanVersionService.createSupplyPlanVersion(resultmap.getKey(), resultmap.getValue(), Constants.SYS);
                                                    }catch (Exception e){
                                                        logger.error("###################     RefreshPriceVersionByMymRooms    供货自动生成刷新:"+e.getMessage(), e);
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                            }else if (versionState.equals(VersionStatusEnum.APPROVED.getKey())){
                                //修改添加代办消息
                                try{
                                    mymRoomInfoServiceImpl.noticeDownsRecordProcessedInfo(priceVersion.getCountingSystemCode().equals(Constants.MY)?Constants.NOTICE_MY_DELAY:Constants.NOTICE_NOS_DELAY, null, priceVersion.getId(), priceVersion.getProjectId(), priceVersion.getProjectfId(), ProcessingStateEnum.UNTREATED.getKey(), ProcessingModeEnum.SYSTEM_DELAY.getKey(), Constants.CLICK, now);
                                }catch (Exception e){
                                    logger.error("################ 添加代办消息 error :"+e.getMessage(), e);
                                }
                            }
                        }else{
                            if (!versionType.equals(VersionTypeEunm.INVESTMENT.getKey())){
                                try {
                                    String versionId =  createSysAppointDynamicVersion(priceVersion.getProjectfId(), priceVersion, null, ascriptionDate, "实际数据刷新生成", 3, null, Constants.CLICK);

                                    supplyPlanVersionService.createSupplyPlanVersion(versionId, VersionTypeEunm.DYNAMIC.getKey(), Constants.SYS);
                                } catch (Exception e) {
                                    logger.error("###################     货值自动生成:"+e.getMessage(), e);
                                }
                            }
                        }
                    }
                }
            }catch (Exception e){
                logger.error("#########  货值变动 错误信息："+e.getMessage(), e);
            }finally {
                synchrolockUtil.unlock(Constants.RedisSyncKey);
                logger.info("====同步锁解锁成功====");
            }
        }
    }

	@Override
	public void batchrefreshPriceValue(String yearmonth,String projectFid, String versionId,String type) {
		if(yearmonth.equals("2021-06")) {
			 logger.info("################ 六月数据刷新开始");
			 List<PriceVersion> list = priceVersionMapper.selectListByDate(yearmonth);
	         for(PriceVersion priceVersion : list) {
	        	if(StrUtils.isNotEmpty(projectFid) && !projectFid.equals(priceVersion.getProjectfId())) {
	        		continue;
	        	}
         		try {
					if(type.equals("1")) {
						priceRefreshActual(priceVersion.getProjectfId(), priceVersion, null,LocalDateTime.now(), Constants.CLICK, null);
					}else {
						supplyPlanVersionService.finalizeCreateSupplyPlanVersion(priceVersion.getId(), priceVersion.getVersionType(), Constants.SYS);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
	         }
	         logger.info("################ 六月数据刷新完成");
		}else {
			logger.info("################ 七月数据刷新开始");
			List<PriceVersion> list2 = priceVersionMapper.selectListByDate2(yearmonth);
	         for(PriceVersion priceVersion : list2) {
	        	if(StrUtils.isNotEmpty(projectFid) && !projectFid.equals(priceVersion.getProjectfId())) {
		        	continue;
		        }
          		try {
					if(type.equals("1")) {
						priceRefreshActual(priceVersion.getProjectfId(), priceVersion, null,LocalDateTime.now(), Constants.CLICK, null);
	         		}else {
	         			supplyPlanVersionService.createSupplyPlanVersion(priceVersion.getId(), priceVersion.getVersionType(),Constants.SYS);
	         		}
				} catch (Exception e) {
					e.printStackTrace();
				}
	          }
	         logger.info("################ 七月数据刷新完成");
		}
         
	}

	@Override
	public List<String> selectBuildListByVersionId(String id) {
		return priceValueOrgMapper.selectBuildListByVersionId(id,IsDeleteEnum.NO.getKey());
	}

	
}
